Python基础-创建简单的TCP Socket服务端和客户端



大家都知道socket是用来在网络中传输数据,是一种跨进程交换数据的常用方式。这里将基于Python的TCP socket实现一个简单的Server和Client的例子,作为Python socket编程的入门学习,同时也会讨论一些重要的注意事项。

Python socket模块实现了基础的socket API的接口,封装了对操作系统级的网络接口调用。常见的一些API如下:

Python TCP Socket

创建socket使用如下代码

Import socket
socket1=socket.Socket(socket.AF_INET, socket.SOCK_STREAM)

代码中的socket.AF_INET 代表我们使用IPV4地址通信,socket.SOCK_STREAM 代表我们创建的一个TCP连接。TCP协议是可靠的连接协议,数据会按照发送的顺序到达客户端,传输过程中发生丢包,发送方会重新发送;而对应的UDP是不可靠的连接,不能保证发送的数据能全部到达接受方,也不会保证数据的先后顺序。

本文例子的数据流图

左侧是服务器端,右侧是客户端,服务器端创建socket后,绑定一个端口开始监听客户端的连接,客户端使用connect连接后,发送数据给服务器端,服务器端回传数据后,客户端主动断开连接,服务器端收到客户端断开信号后断开连接。

Server服务器端

下面是server的实现

import socket
HOST = "127.0.0.1"
PORT = 12345
socket1=socket.socket(socket.AF_INET, socket.SOCK_STREAM)#创建tcp socket
socket1.bind((HOST, PORT))#绑定端口
socket1.listen(1) #开始监听
conn, addr = socket1.accept() #阻塞等待客户端连接
while True:
    try:
        data = conn.recv(1024)
        if not data:#客户端断开了连接
           conn.close()
           break
        conn.sendall(data)#发送数据
    except Exception as e:
        print(e)

下面解析一下server的代码

socket1=socket.socket(socket.AF_INET, socket.SOCK_STREAM)

这里创建了TCP协议的socket ,其中socket.AF_INET代表使用IPV4地址,socket.SOCK_STREAM代表这里创建的是TCP协议的Socket

socket1.bind((IP, PORT))

这一句用来将socket绑定在确定的主机和端口上,主机可以是IP也可以是域名。这里是本机测试所以填写的是127.0.0.1 ,这代表着本server只能被本机的client访问,如果希望能接收所有地址的客户端的访问,IP地址可以填写空字符串或者”0.0.0.0”,如下。

socket1.bind(("", PORT)) or socket1.bind(("0.0.0.0", PORT))

PORT TCP端口的范围是1-65535,建议使用1024以上的端口。

socket1.listen(1)

listen() 意味着服务器端socket开始监听接受连接,listen有一个可选的整数参数,代表者本服务器最多能接收多少个连接,在本例中是1,代表只能接受一个连接,需要注意的是Linux下能建立的Socket数量是受资源限制的。

conn, addr = socket1.accept() 

accept()是一个阻塞API,等待客户端的连接。当客户端连接成功时这个函数会返回一个新的socket对象和客户端地址信息的元组,服务器将使用这个新的socket和和客户端交互数据。

while True:
    try:
        data = conn.recv(1024)
        if not data:#客户端断开了连接
           conn.close()
           break
        conn.sendall(data)#发送数据
    except Exception as e:
        print(e)

成功建立连接收使用recv()接收客户端发送的数据,使用sendall()发送接收到的数据。这里接收recv()的参数buffsize这里设置是1024,但是需要注意的是1024是代表一次能返回的最大字节数,不是代表一定要返回1024个字节。

同样的在本例中的sendall()函数对应的另一个发送数据api是send(),他们的区别是send()不能保证一次把所有的数据都发送完成,send()函数的返回是成功发送的字节数,而sendall() 会持续发送数据,直到所有的数据都发送完成或者报错退出。

如何获知客户端主动关闭了连接

if not data:
     conn.close()

如果客户端主动关闭了连接,recv()函数会立刻返回空b’’ ,服务器这时需要判断空数据,并断开连接,如本例的实现,此处是初学者容易虎忽略的地方。

Client 客户端

客户端的实现如下所示

import socket
PORT = 12345
socket1=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
      socket1.connect(("127.0.0.1" , PORT)) #连接服务器
      socket1.sendall(b"Hello, world") #发送数据
      data = socket1.recv(1024) #接收数据
      print(data)
      socket1.close() #关闭连接
except Exception as e:
   print(e)

客户端的实现相对简单一些,首先创建socket 连接服务器,然后发送数据并接收数据后关闭连接。

运行server和client

打开一个控制台窗口,先运行服务器端

python server.py

服务器端会阻塞在accept()处,等待连接

打开新的控制台窗口,然后运行客户端

python client.py

客户端连接成功后,在交互数据后客户端会先退出,然后server端也跟着退出。

总结:

本文介绍了Python Socket的基本使用,实现了一个简单的服务器和客户端的交互,此处的服务器只支持一个客户端的连接,在后面的文章中介绍如何实现一个支持多连接的Python socket服务器

原文链接:,转发请注明来源!