一、环境
1.1 客户端:windows宿主机
1.2 服务器端:Linux虚拟机
1.3 注意事项
测试套接字编程通信时,先确保C/S能互相ping通,且双方主机防火墙允许目的端口号为“创建的端口号”的数据包通过。
二、代码
2.1 UDP套接字编程
2.1.1 UDPClient.py
from socket import * # 导入套接字编程所需包# 一个目的地址由(serverName, serverPort)构成。
serverName = 'Write your server IP address(example:192.168.1.1) or domain name(example:www.zhihu.com)'
serverPort = 12000
clientSocket = socket(AF_INET, SOCK_DGRAM) # 该行创建一个客户端套接字。第一个参数指示底层网络使用IPv4;第二个参数指示该套接字是UDP套接字,由操作系统自动创建clientSocket的端口号
message = input('Input lowercase sentence:')
# 下面使用encode()方法将报文由字符串类型编码为字节序列,同时使用sendto方法为报文附上服务器地址(serverName, serverPort)并向进程的clientSocket套接字发送分组
clientSocket.sendto(message.encode(),(serverName, serverPort))
# 下面使用recvfrom()方法,将到达该客户端套接字的分组中的数据放入modifiedMessage中,将该分组的源地址放到变量serverAddress中。
modifiedMessage, serverAddress = clientSocket.recvfrom(2048)
print(modifiedMessage.decode()) # 将字节类型的modifiedMessage解码转换为字符串类型并输出。
clientSocket.close() # 关闭创建的套接字
2.1.2 UDPServer.py
from socket import *serverPort = 12000
serverSocket = socket(AF_INET, SOCK_DGRAM)
serverSocket.bind(('', serverPort)) # 该行将端口号12000与该serverSocket套接字绑定
print("Server is ready to receive.")
while True: # 保持服务器该套接字始终工作,接收来自客户端的分组message, clientAddress = serverSocket.recvfrom(2048) # 该处代码解释同客户端,其中print(clientAddress)的结果为('IP address', portNumber)modifiedMessage = message.decode().upper() # 将接收到的字符串全部转为大写serverSocket.sendto(modifiedMessage.encode(), clientAddress) # 将信息发回给客户端
2.2 TCP套接字编程
2.2.1 TCPClient.py
from socket import *serverName = 'Write your server IP address(example:192.168.1.1) or domain name(example:www.zhihu.com)'
serverPort = 12000
clientSocket = socket(AF_INET, SOCK_STREAM) # SCOK_STREAM指示该套接字是TCP套接字,由操作系统自动创建clientSocket的端口号
clientSocket.connect((serverName, serverPort)) # 请求建立TCP连接
sentence = input('Input lowercase sentence:')
clientSocket.send(sentence.encode()) # 已建立TCP连接后,后续通过该套接字发送数据均不再需要指明目的服务器地址。
modifiedSentence = clientSocket.recv(1024)
print('From Server:', modifiedSentence.decode())
clientSocket.close()
2.2.2 TCPServer.py
from socket import *serverPort = 12000
serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.bind(('',serverPort)) # 该行将端口号12000与该serverSocket套接字绑定,注意,这个serverSocket套接字是我们的欢迎套接字。
serverSocket.listen(1) # 欢迎套接字监听来自客户的TCP连接请求,且参数规定了请求连接的最大数目。
print('Server is ready to recvive')
while True:connectionSocket, addr = serverSocket.accept() # 当有TCP连接请求时,欢迎套接字使用accept()方法创建一个专用于服务该请求的connectionSocket连接套接字sentence = connectionSocket.recv(1024).decode()modifiedSentence = sentence.upper() # 将收到的数据转为大写connectionSocket.send(modifiedSentence.encode()) # 将转为大写后的数据发回客户端connectionSocket.close() # 关闭该连接套接字。
# 需要注意,欢迎套接字创建完连接套接字后,有关该请求连接客户的所有事项均由连接套接字接管,包括TCP的三次握手及后续的数据传输和连接关闭对话
三、当前问题(待更新解答)
3.1 在UDPServer.py中有一条语句:message, clientAddress = serverSocket.recvfrom(2048)。为什么clientAddress是二元组(IP_address,port _number)?
四、参考资料
计算机网络:自顶向下方法(第8版)