基于socket实现客户端与服务器之间TCP通信

我们在算法部署时,通常需要进行算法端与其他服务端的通信,要么接受指令、要么是需要上传算法结果;除了我们常用的gRPC、HTTP、MQ等方式,还可以利用TCP来实现可靠通信;本次我们利用socket来展示如何进行两端的TCP通信。

目录

一、概念

二、示例代码

[1. 服务端](#1. 服务端)

[2. 客户端](#2. 客户端)

[3. 实现效果](#3. 实现效果)

参考:


一、概念

  1. TCP(传输控制协议)

    • TCP是一种传输层通信协议,位于OSI模型的第四层。
    • 它负责在网络中的两个主机之间提供可靠的、有序的和错误检测功能的数据传输。
    • TCP确保数据包正确无误地从源传送到目的地,如果数据在传输过程中丢失或损坏,TCP会重新发送数据直到接收方正确接收到所有数据。
    • TCP是面向连接的协议,这意味着在数据传输开始之前,必须在两端建立一个连接。
  2. Socket(套接字)

    • 套接字是网络编程中的一个端点,它提供了一种方式,允许设备上的应用程序发送和接收数据。
    • 套接字是TCP/IP网络通信的一个抽象概念,它将网络协议栈封装为一个编程接口,使得开发者可以不必关心底层的网络细节。
    • 在操作系统中,套接字用于实现TCP/IP模型的通信,它们可以基于不同的协议,如TCP、UDP(用户数据报协议)等。
    • 套接字编程通常涉及创建套接字、绑定到一个地址和端口、监听连接(对于服务器)、接受或发起连接(对于客户端)、发送和接收数据,以及关闭连接。

二、示例代码

1. 服务端

实现思路:

  • 创建Socket对象

    • 使用 socket.socket(socket.AF_INET, socket.SOCK_STREAM) 创建一个新的socket对象,用于TCP通信。
  • 绑定主机名和端口号

    • host = '127.0.0.1' 表示服务器监听本地回环地址。
    • port = 9998 指定服务器监听的端口号。
    • server_socket.bind((host, port)) 将socket与主机名和端口号绑定。
  • 监听连接

    • server_socket.listen(5) 开始监听连接,参数5表示允许最多5个客户端连接等待接受。
  • 接受连接

    • while True: 循环中,server_socket.accept() 等待并接受客户端的连接请求,返回一个新的socket对象 client_socket 和客户端地址 addr
  • 接收和发送数据

    • 在另一个 while True: 循环中,client_socket.recv(1024) 接收客户端发送的数据,最大接收1024字节。
    • 如果接收到的数据为空,表示客户端关闭了连接,跳出循环。
    • 否则,将接收到的字符串数据尝试反序列化为字典:json.loads(data.decode('utf-8'))
    • 如果成功,打印接收到的字典数据,并将相同的字典数据序列化回字符串发送给客户端:client_socket.send(json.dumps(received_dict).encode('utf-8'))
    • 如果数据格式错误,捕获 json.JSONDecodeError 异常并打印错误信息。
python 复制代码
import socket
import json


def tcp_server():
    # 创建socket对象
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 获取本地主机名
    host = '127.0.0.1'

    # 设置一个端口号
    port = 9998

    # 绑定端口号
    server_socket.bind((host, port))

    # 设置最大连接数,超过后排队
    server_socket.listen(5)

    # 设置超时时间
    # server_socket.settimeout(10)  # 10秒超时

    while True:
        try:
            # 建立客户端连接
            client_socket, addr = server_socket.accept()

            print("连接地址: %s" % str(addr))

            while True:
                try:
                    # 接收小于 1024 字节的数据
                    data = client_socket.recv(1024)

                    if not data:
                        # 如果没有数据,跳出循环
                        break
                    else:
                        # 打印接收的数据
                        print("收到数据:", data.decode('utf-8'))

                        # 尝试将接收到的字符串数据反序列化为字典
                        try:
                            received_dict = json.loads(data.decode('utf-8'))
                            print("接收到的字典数据:", received_dict)

                            # 发送响应数据给客户端,这里发送相同的字典
                            client_socket.send(json.dumps(received_dict).encode('utf-8'))
                        except json.JSONDecodeError as e:
                            print("数据格式错误,无法解析为字典:", e)
                except socket.timeout:
                    print("接收数据超时")
                    break
        except ConnectionResetError:
            print("连接被客户端重置")
        finally:
            # 关闭连接
            if client_socket:
                client_socket.close()


if __name__ == '__main__':
    tcp_server()

2. 客户端

实现思路:

  • 创建Socket对象

    • 同服务器端,使用 socket.socket(socket.AF_INET, socket.SOCK_STREAM) 创建一个新的socket对象。
  • 连接到服务器

    • host = '127.0.0.1'port = 9998 指定服务器的地址和端口号。
    • client_socket.connect((host, port)) 连接到服务器。
  • 发送和接收数据

    • while True: 循环中,通过 input("请输入数据:") 获取用户输入的数据,并发送到服务器:client_socket.send(data.encode('utf-8'))
    • 接收服务器返回的数据:client_socket.recv(1024)
    • 打印来自服务器的数据:print("来自服务器的数据:%s" % data.decode('utf-8'))
    • 如果接收到的数据是 'exit',则跳出循环。
  • 关闭连接

    • 在循环结束后,关闭客户端socket连接。
python 复制代码
import socket
import json
import time
from tcp_messaging.api.core.tcp_messaging import TcpClient


def main():
    # 获取本地主机名
    host = '127.0.0.1'
    # 设置服务器的端口号
    port = 9998

    client = TcpClient((host, port), name='client1')
    client.connect()

    # 创建一个字典
    send_dict = {'key1': 'value1', 'key2': 'value2'}
    # 将字典序列化为JSON格式的字符串
    send_data = json.dumps(send_dict).encode('utf-8')
    client.send(send_data)
    time.sleep(1)
    if client.recv(1024):
        print("received success!")

    client.close()


if __name__ == '__main__':
    main()

3. 实现效果

客户端发送的数据及接收的返回数据:

服务端接收的数据:

参考:

https://en.wikipedia.org/wiki/Transmission_Control_Protocol

https://en.wikipedia.org/wiki/Network_socket

TCP(传输控制协议)_百度百科

套接字_百度百科

相关推荐
Graceful_scenery1 分钟前
https双向认证
服务器·网络·网络协议·http·https
njnu@liyong11 小时前
图解HTTP-HTTP状态码
网络协议·计算机网络·http
昌sit!13 小时前
监控IP频繁登录服务器脚本
服务器·网络·tcp/ip
代码洁癖症患者14 小时前
HTTP请求的奇幻旅程:从发起至响应的全方位探索
网络·网络协议·http
凹凸撒man14 小时前
AUTOSAR TCP中的MSS和MTU的关系
网络·tcp/ip·autosar
岳不谢14 小时前
华为DHCP高级配置学习笔记
网络·笔记·网络协议·学习·华为
龙少954316 小时前
【深入理解网络协议】
网络·网络协议
寻找沙漠的人17 小时前
HTTP—02
网络·网络协议·http
范紫涵-19期-工职大20 小时前
前端HTTP协议传输以及背后的原理总结
网络·网络协议·http
Hacker_LaoYi20 小时前
网络协议栈学习(一)socket通信实例
网络·网络协议·学习