socket编程(基于TCP/UDP协议的通信)

基于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()

你可能感兴趣的:(socket编程(基于TCP/UDP协议的通信))