TCP服务器程序
import socket
def tcp_server():
# 创建一个TCP套接字对象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# AF_INET表示使用IPv4地址族,SOCK_STREAM表示使用TCP协议
# 设置套接字选项,以便在程序重新启动时可以重用地址
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 绑定服务器地址和端口
server_address = ('127.0.0.1', 12345)
server_socket.bind(server_address)
# 开始监听,最大连接数为5
server_socket.listen(5)
print('Server is listening on {}:{}'.format(*server_address))
while True:
# 接受客户端连接
client_socket, client_address = server_socket.accept()
print('Accepted connection from {}:{}'.format(*client_address))
# 接收客户端发送的数据,最多接收1024字节
data = client_socket.recv(1024)
if data:
# 将接收到的字节数据解码为字符串
received_string = data.decode('utf-8')
print('Received string:', received_string)
# 反转字符串
reversed_string = received_string[::-1]
# 将反转后的字符串编码为字节数据并发送回客户端
client_socket.send(reversed_string.encode('utf-8'))
# 关闭与客户端的连接
client_socket.close()
if __name__ == '__main__':
tcp_server()
TCP客户端程序
import socket
def tcp_client():
# 创建一个TCP套接字对象
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 连接到服务器
server_address = ('127.0.0.1', 12345)
client_socket.connect(server_address)
# 要发送的字符串
send_string = 'Hello, Server!'
# 将字符串编码为字节数据并发送到服务器
client_socket.send(send_string.encode('utf-8'))
# 接收服务器返回的数据,最多接收1024字节
data = client_socket.recv(1024)
if data:
# 将接收到的字节数据解码为字符串
received_string = data.decode('utf-8')
print('Received reversed string:', received_string)
# 关闭套接字
client_socket.close()
if __name__ == '__main__':
tcp_client()
每一步的作用及涉及到的TCP相关概念
- 创建套接字:
- 在服务器和客户端都使用
socket.socket(socket.AF_INET, socket.SOCK_STREAM)
创建套接字。AF_INET
表示使用IPv4地址族,这是目前广泛使用的互联网协议版本。SOCK_STREAM
表示使用TCP协议,TCP是一种面向连接的、可靠的传输协议,它通过三次握手建立连接,保证数据的有序传输和完整性。
- 服务器端:
- 设置套接字选项:
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
允许程序在重新启动时重用地址。这在开发和调试过程中很有用,因为如果不设置此选项,程序关闭后,可能需要等待一段时间才能再次绑定到相同的地址和端口。
- 绑定地址和端口:
server_socket.bind(server_address)
将服务器套接字绑定到指定的地址(127.0.0.1
即本地回环地址,表示只接受本地连接,实际应用中可能会使用公网IP)和端口(12345
)。端口用于标识服务器上的特定服务,不同的服务使用不同的端口号。
- 监听连接:
server_socket.listen(5)
使服务器进入监听状态,等待客户端的连接请求。参数 5
表示最大连接数,即服务器在拒绝新的连接请求之前可以同时处理的未完成连接数。
- 接受连接:
client_socket, client_address = server_socket.accept()
阻塞等待客户端连接。一旦有客户端连接,它返回一个新的套接字对象 client_socket
用于与该客户端进行通信,以及客户端的地址 client_address
。
- 接收和处理数据:
data = client_socket.recv(1024)
从客户端接收数据,1024
表示最多接收1024字节的数据。接收到的数据是字节类型,需要解码为字符串。然后将字符串反转并编码为字节数据发送回客户端。
- 关闭连接:
client_socket.close()
关闭与客户端的连接,释放资源。
- 客户端:
- 连接服务器:
client_socket.connect(server_address)
客户端使用此方法连接到服务器指定的地址和端口。这是TCP三次握手的发起步骤,客户端向服务器发送SYN(同步)包,服务器响应SYN + ACK(同步确认)包,客户端再发送ACK包,从而建立连接。
- 发送数据:
client_socket.send(send_string.encode('utf-8'))
将字符串编码为字节数据并发送到服务器。
- 接收数据:
data = client_socket.recv(1024)
接收服务器返回的数据并解码为字符串进行显示。
- 关闭连接:
client_socket.close()
关闭套接字,释放资源,同时也会向服务器发送FIN(结束)包,发起连接关闭的过程。