使用Python搭建TCP客户端与服务端

Kiaana Lv2

TCP协议简介

传输控制协议 (TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。

计算机之间的通信需要使用Socket套接字 ,Python标准库中已内置Socket模块。

TCP客户端和服务器通信流程如下:

对于TCP服务端建立:

  1. 创建TCP套接字
  2. 关联本地端口与插座
    • 绑定端口后客户端才能访问
  3. 设置套接字监听模式
    • 设置为被动模式,不能主动发起请求,只能被动等待连接
  4. 接受来自客户端的新连接
    • 三次握手建立连接
  5. 接收和发送数据
  6. 关闭客户机/服务器连接
  7. 返回到步骤4

对于TCP客户端建立:

  1. 创建TCP套接字
  2. 连接到TCP服务器
  3. 发送数据/接收数据
  4. 关闭连接
    • 发起关闭连接通知
    • 四次挥手后断开连接

TCP工作原理

TCP三次握手


搭建TCP客户端

接下来就来利用Python搭建一个简单的TCP客户端,实现局域网内通信。

流程如下:

  1. 创建客户端套接字对象 socket()
  2. 和服务器套接字建立连接 connect()
  3. 发送数据 send()
  4. 接受数据 recv()
  5. 关闭客户端套接字 close()

至于TCP协议和Socket的实现原理可自行查阅相关资料。

首先,导入Socket模块

1
import socket

创建套接字对象

  • 使用socket.socket(AddressFamily, Type)返回一个socket对象
    • AddressFamily: 表示IP地址类型,分为IPv4和IPv6
      • socket.AF_INET: IPv4
    • Type: 表示传输协议类型
      • SOCK_STREAM: TCP传输协议
      • SOCK_DGRAM: UDP传输协议
  • 默认参数即为socket.AF_INET, socket.SOCK_STREAM
1
tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

和服务端建立连接

  • connet()方法仅接受一个元组参数,元组中包含IP和端口(服务端的IP和端口)
1
2
3
tcp_client_socket.connet(('192.168.26.70', 7777))
print('连接成功')
# 代码执行到此表示连接建立成功

准备发送的数据

  • 服务端为Windows用gbk,Mac和Linux为utf-8
1
send_data = '你好服务端,我是客户端'.encode('utf-8')

发送数据

  • 发送和接受数据都是以二进制字节流的形式进行
1
tcp_client_socket.send(send_data)

接收数据

  • recv(bytes) 方法接收服务端发来的数据,返回二进制数据
  • bytes参数指定接收的数据最大字节数为1024
1
recv_data = tcp_client_socket.recv(1024)

对数据进行解码,由于数据传输形式是二进制,需解码才能正常显示

1
2
recv_content = recv_data.decode('utf-8')
print(recv_content)

断开连接

1
tcp_client_socket.close()

以下是完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
'''
1. 创建客户端套接字对象 socket()
2. 和服务器套接字建立连接 connect()
3. 发送数据 send()
4. 接受数据 recv()
5. 关闭客户端套接字 close()
'''

import socket
# 导入socket模块

if __name__ == '__main__':
# 创建tcp客户端套接字
# 1. AF_INET: 表示IPv4
# 2. SOCK_STREAM: TCP传输协议
# 3. SOCK_DGRAM: UDP传输协议
# 默认参数 socket.AF_INET, socket.SOCK_STREAM
tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 和服务端应用程序建立连接
tcp_client_socket.connect(('192.168.26.70', 7777))
print('连接成功')
# 代码执行到此,说明连接建立成功

# 准备发送的数据
# 服务端为Windows用gbk,Mac和Linux为utf-8
send_data = '你好服务端,我是客户端'.encode('utf-8')

# 发送数据
tcp_client_socket.send(send_data)

# 接受数据,指定接受的数据最大字节数是1024,最大4096
recv_data = tcp_client_socket.recv(1024)

# 返回的直接是服务端程序发送的二进制数据
# print(recv_data)

# 对数据进行解码
recv_content = recv_data.decode('utf-8')
print(recv_content)

# 断开连接
tcp_client_socket.close()

搭建TCP服务端

搭建完客户端,来搭建一个客户端尝试连接

  1. 创建服务端套接字对象 socket()
  2. 绑定端口号 bind()
  3. 设置监听 listen()
  4. 等待接受客户端的连接请求 accept()
  5. 接收数据 recv()
  6. 发送数据 send()
  7. 关闭套接字 close()

首先导入socket模块

1
import socket

创建tcp服务端套接字

1
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

绑定ip和端口

  • 如果在绑定IP时,没有给定IP,默认绑定的是本地IP地址
  • bind()方法仅接受一个元组参数,元组中包含IP和端口(服务端的IP和端口)
1
tcp_server_socket.bind(('', 7777))

设置监听

  • 使用listen()方法设置监听
  • 设置监听后,服务端进入被动模式,只能被动连接,连接前会一直等待
1
2
tcp_server_socket.listen(128)
print('监听中···')

等待客户端连接

接受连接

  • accpet()会返回两个数据,一个是客户端的Socket对象,另一个是客户端的地址信息
1
2
client_socket, ip_port = tcp_server_socket.accept()
print(f'客户端{ip_port[0]} 使用端口{ip_port[1]} 连接成功')

接受客户端的数据

  • 如果接收的数据长度为0说明客户端发送了断开连接请求
1
2
3
4
5
data_recv = client_socket.recv(1024).decode('utf-8')
if len(data_recv):
print(f'客户端 {ip_port[0]} 发送的数据是 {data_recv}')
else:
print(f'客户端{ip_port[0]} 断开连接')

给客户端发送数据

1
2
data_send = '已收到'.encode('utf-8')
client_socket.send(data_send)

关闭客户端

1
client_socket.close()

关闭服务端

1
tcp_server_socket.close()

完整代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
'''
1. 创建服务端套接字对象 socket()
2. 绑定端口号 bind()
3. 设置监听 listen()
4. 等待接受客户端的连接请求 accept()
5. 接收数据 recv()
6. 发送数据 send()
7. 关闭套接字 close()
'''


import socket


if __name__ == '__main__':
# 创建tcp服务端套接字
# 如果马上重启服务器时会出现错误,因为地址和端口没有被释放
# OSError: [Errno 48] Address already in use
# 如果想马上释放,要设置socket选项
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 设置socket选项
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)

# 绑定IP和端口
# 如果在绑定ip时,没有给定ip,默认绑定的时本地ip地址
tcp_server_socket.bind(('', 7777))

# 设置监听
# 设置监听后服务端进入被动模式,只能被动接受连接
tcp_server_socket.listen(128)
print('监听中···')

# 等待客户端连接
# 如果客户连接上来后,该函数会返回两个数据,一个是客户端的Socket对象,另一个是客户端的地址信息
client_socket, ip_port = tcp_server_socket.accept()
print(f'客户端{ip_port[0]} 使用端口{ip_port[1]} 连接成功')

# 接受客户端的数据
data_recv = client_socket.recv(1024).decode('utf-8')
if len(data_recv):
print(f'客户端 {ip_port[0]} 发送的数据是 {data_recv}')
else:
print(f'客户端{ip_port[0]} 断开连接')

# 给客户端发送数据
data_send = '已收到'.encode('utf-8')
client_socket.send(data_send)

# 关闭客户端
client_socket.close()

# 关闭服务端
tcp_server_socket.close()

# 设置端口号复用,让程序退出端口号立即释放
  • 标题: 使用Python搭建TCP客户端与服务端
  • 作者: Kiaana
  • 创建于 : 2022-04-20 19:58:04
  • 更新于 : 2023-09-21 17:53:09
  • 链接: https://www.kiaana.cn/posts/python-tcp-client-server/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
 评论
此页目录
使用Python搭建TCP客户端与服务端