基于tcp的通信
TCP把连接作为最基本的对象,每一条TCP连接都有两个端点,这种断点我们叫作套接字(socket)
服务端:
import socket
# 1. 创建一个socket对象;
# family指定使用IP协议的版本: IPV4:AF_INET; ipv6: AF_INET6
# type指定传输层使用的协议类型:TCP(SOCKET.SOCK_STREAM), UDP(SOCK_DGRAM)
server=socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)
# 2. 绑定一个IP和端口, 供客户端来连接;
server.bind(('172.25.254.67', 4002))
# 3. 监听是否有客户端连接
server.listen(5)
print("服务端正在启动.........")
# 4. 接收客户端的连接, accept() -> (socket object, address info)
clientSocket,address=server.accept()
print("客户端的地址:", address)
# 5. 接收客户端发送的消息
recvData=clientSocket.recv(1024)
print("服务端接收的消息:", recvData.decode('utf-8'))
# 6. 给客户端回复消息, send(self, data: **bytes***, flags: int = ...) -> int: ...
clientSocket.send('你好, 客户端'.encode('utf-8'))
# 7. 关闭服务端socket对象
server.close()
clientSocket.close()
客户端:
import socket
# 1. 创建一个socket对象;
# family指定使用IP协议的版本: IPV4:AF_INET; ipv6: AF_INET6
# type指定传输层使用的协议类型:TCP(SOCKET.SOCK_STREAM), UDP(SOCK_DGRAM)
client = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
# 2. 连接服务端(ip, port)
client.connect(('172.25.254.67', 4002))
# 3. 给服务端回复消息, send(self, data: **bytes***, flags: int = ...) -> int: ...
client.send("你好, 服务端".encode('utf-8'))
# 4. 接收服务端回复的消息
recvData = client.recv(1024)
print("客户端接收的消息:", recvData.decode('utf-8'))
# 7. 关闭客户端socket对象
client.close()
基于TCP实现socket编程的多线程通信
因为在子进程中不能存在输入input,否则会报错,所以采用线程
server主机:
import threading
def get_client_conn(clientSocket, address):
while True:
# 5. 接收客户端发送的消息
recvData=clientSocket.recv(1024)
print("服务端接收的消息:", recvData.decode('utf-8'))
# 6. 给客户端回复消息
sendData = input('server:>> ')
if not sendData:
continue
if sendData == 'quit':
print("聊天结束.....")
break
clientSocket.send(sendData.encode('utf-8'))
clientSocket.close()
import socket
# 1. 创建一个socket对象;
# family指定使用IP协议的版本: IPV4:AF_INET; ipv6: AF_INET6
# type指定传输层使用的协议类型:TCP(SOCKET.SOCK_STREAM), UDP(SOCK_DGRAM)
server=socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)
# 2. 绑定一个IP和端口, 供客户端来连接;
server.bind(('172.25.254.67',4007))
# 3. 监听是否有客户端连接
server.listen(5)
print("服务端正在启动.........")
while True:
# 4. 接收客户端的连接
clientSocket,address=server.accept()
print("客户端的地址:", address)
t=threading.Thread(target=get_client_conn,args=(clientSocket,address))
t.start()
# 7. 关闭服务端socket对象get
# server.close()
#client主机(可以多台主机与服务主机通信):
import socket
client=socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)
client.connect(('172.25.254.67',4007))
while True:
sendData=input('client:>> ')
if not sendData:
continue
if sendData=='quit':
print('聊天结束...')
break
client.send(sendData.encode('utf-8'))
recvData=client.recv(1024)
print("客户端接收的消息:", recvData.decode('utf-8'))
if recvData.decode('utf-8')=='quit':
break
# 7. 关闭客户端socket对象
client.close()
结果显示
# server端:
服务端正在启动.........
客户端的地址: ('172.25.254.67', 45484)
客户端的地址: ('172.25.254.67', 45485)
服务端接收的消息: hello
server:45484>> hello
服务端接收的消息: nice
server:45485>> not good
服务端接收的消息:
server:45484>> 聊天结束.....
# client端:
client:>> hello
客户端接收的消息: hello
client:>> quit
聊天结束...
client1:>> nice
客户端接收的消息: not good
client1:>>
基于UDP的通信
server端:
# 实现: udp多个客户端可以连接服务端, 发送命令, 返回的是命令的执行结果;
import socket
# 1. 实例化socket对象
udpServer = socket.socket(family=socket.AF_INET,type=socket.SOCK_DGRAM)
# 2. 绑定IP和端口
# 0.0.0.0代表开放所有的IP地址
udpServer.bind(('0.0.0.0', 9001))
print("等待客户端UDP的连接.....")
# 3. 接收客户端的连接
recvdata, address = udpServer.recvfrom(1024)
print("接收到客户端的数据: ", recvdata.decode('utf-8'))
# 4. 给客户端回复消息
udpServer.sendto(b"hello client", address)
# 5. 关闭socket对象
udpServer.close()
client端:
import socket
udpClient = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
udpClient.sendto(b'hello server', ('172.25.254.67', 9001))
recvData, address = udpClient.recvfrom(1024)
print("接收服务端的数据: ", recvData.decode('utf-8'))
udpClient.close()
UDP实现多线程通信
server端:
import socket
import os
import threading
def job():
cmd , address=server.recvfrom(1024)
cmd=cmd.decode('utf-8')
print("接收到客户端的命令: ", cmd)
cmdres=os.popen(cmd).read().encode('utf-8')
server.sendto(cmdres,address)
server=socket.socket(family=socket.AF_INET,type=socket.SOCK_DGRAM)
server.bind(('0.0.0.0',9003))
print('等待客户端的连接...')
while True:
t=threading.Thread(target=job,args=(,))
t.start()
server.close()
# client端:
import socket
client=socket.socket(family=socket.AF_INET,type=socket.SOCK_DGRAM)
while True:
cmd = input("client:>> ").encode('utf-8')
if not cmd:
continue
if cmd == 'quit':
print("正在退出....")
break
client.sendto(cmd,('172.25.254.67',9003))
recvData,adress=client.recvfrom(1024)
if recvData.decode('utf-8')=='quit':
break
print("接收服务端的数据: ", recvData.decode('utf-8'))
client.close()
模拟urllib实现网页内容的获取
# 实现http客户端的程序, 获取百度页面
import socket
# http://www.baidu.com:80
# 实例化socket对象; 默认参数指定为IPv4协议, 和TCP传输协议;
client = socket.socket()
# 连接服务器端
client.connect(('www.baidu.com', 80))
# 给百度服务器发送请求通过GET方法请求主页内容的请求, http协议的版本为1.1;
client.send(b'GET / HTTP/1.1\r\nHost:www.baidu.com\r\nConnection:close\r\n\r\n')
# 接收服务端返回的页面内容;
recvData = client.recv(1024*100)
# 解码为能够识别的字符串;
print(recvData.decode('utf-8'))
# 关闭客户端连接;
client.close()
实现简易的Web服务器端
import socket
def handler(clientObj):
# 5. 接收客户端发送的请求
recvData = clientObj.recv(1024)
with open('hello.html', 'rb') as f:
sendData = f.read()
# 告诉浏览器http版本
clientObj.send(b'HTTP/1.1 200 ok\r\n\r\n')
clientObj.send(sendData)
def webServer():
# 1. 创建socket对象
server = socket.socket()
# 2. 绑定端口和ip
server.bind(('0.0.0.0', 8084))
# 3. 监听是否有客户端连接
server.listen(5)
print("http服务正在启动8080........")
while True:
# 4. 接收客户端的连接
clientObj, address = server.accept()
t = threading.Thread(target=handler, args=(clientObj, ))
t.start()
server.close()
if __name__ == '__main__':
webServer()