大师兄的Python学习笔记(十五): Socket编程

2020-04-13  本文已影响0人  superkmi

大师兄的Python学习笔记(十四): 迭代器、生成器和协程
大师兄的Python学习笔记(十六): FTP与ftplib

一、关于互联网的一些基础知识

1.关于程序架构
1.1 C/S架构
1.2 B/S架构
2.关于IP和Port
2.1 关于IP

1)IPv4和IPv6

  • IPv4(Internet Protocol version 4)指的是互联网通信协议的第四版,是第一个被广泛部署的版本。
  • IPv4使用32位(4字节)地址,因此共有43亿(2^32-1)个地址, 全球IPv4地址已于2019年11月26日耗尽。
  • IPv6(Internet Protocol Version 6)指的是互联网通信协议的第六版,是用于替代IPv4的下一代IP协议。
  • IPv6将IPv4中32位的地址长度扩展到了128位,即有2^128-1个地址,可以将地球上每一粒沙子都赋予ip地址。

2)IP地址的分类

类型 号段 说明
A类 1.0.0.0-126.0.0.0 第一个字节为网络号,后三个字节为主机号。
该类IP地址的最前面为“0”,所以地址的网络号取值于1~126之间。
一般用于大型网络。
B类 128.0.0.0-191.255.0.0 前两个字节为网络号,后两个字节为主机号。
该类IP地址的最前面为“10”,所以地址的网络号取值于128~191之间。
一般用于中等规模网络。
C类 192.0.0.0-223.255.255.0 前三个字节为网络号,最后一个字节为主机号。
该类IP地址的最前面为“110”,所以地址的网络号取值于192~223之间。
一般用于小型网络。
D类 最前面为“1110” 多播地址。
地址的网络号取值于224~239之间。
一般用于多路广播用户。
E类 最前面为“1111” 保留地址。
地址的网络号取值于240~255之间。

3)几个需要记住的地址

地址 说明
0.0.0.0 -代表所有'不清楚'的主机和目的网络。
-这里的“不清楚”是指在本机的路由表里没有特定条目指明如何到达。
-对本机来说,它就是一个“收容所”,所有不认识的“三无”人员,一 律送进去。
255.255.255.255 受限广播地址。
对于本机来说,这个地址指本网段内的所有主机。
127.0.0.1 本机地址,主要用于测试。
与"localhost"相同。
192.168.0.1是本机ip地址。
224.0.0.1 组播地址,从224.0.0.0到239.255.255.255都是这样的地址。
224.0.0.1 特指所有主机
224.0.0.2 特指所有路由器。
168.254.x.x Windows操作系统在DHCP信息租用失败时自动给客户机分配的IP地址。
10.x.x.x, 172.16.x.x
~172.31.x.x,192.168.x.x
内网私有地址。
2.2 关于Port

1)Port的基础知识

  • Port(端口)是设备与外界通讯交流的出口。
  • 如果理解互联网是一个社区,每台设备是一栋建筑,ip是楼号,port就是具体的门牌号。
  • Port的范围是0-65535,其中知名端口(已占用)是0-1023。

2)一些常用端口

端口 服务
21 FTP
22 SSH
23 Telnet
25 SMTP
53 DNS(UDP)
69 TFTP(简单文件传输协议)
79 Finger(列出用户的一些信息)
80 HTTP
110 POP3
111 RPC远程过程调用
113 Windows验证服务
119 NNTP网络新闻组传输协议
135 RPC远程过程调用
137 NetBIOS
139 Windows文件和打印机共享, Unix中的Samba服务
161 SNMP简单网络管理协议
389 LDAP
443 HTTPS
445 SMB
1080 Socks代理服务
2601、2604 zebra路由,默认密码zebra
5900 VNC
8080 WWW代理服务
3.关于网络协议
3.1 OSI七层模型
说明
物理层
Physical
- 位于最低层,是传送信号的物理实体。
- 通过机械和电气的方式将各站点连接起来,组成物理通路,以便使数据流通过。
数据链路层
Data Link
- 在物理层所提供的数据传输电路的基础上,提供了一条无差错的数据链路。
- 进行二进制数据流的传输,并进行差错检测和流量控制。
网络层
Network
- 处理报文分组,完成分组的多路复用和分组交换,以及通信子网络间的数据据传输。
传输层
Transport
- 实现端点到端点的可靠数据传输。
会话层
Session
- 用于建立、控制和终止终端用户的实用进程间的逻辑信道的连接。
- 提供支持同步和管理应用进程间的对话服务,验证会话双方的身份,会话连接的恢复和释放。
表示层
Presentation
- 为用户应用进程提供了一系列统一的数据表示方式的服务。
- 解决不同系统不同终端所用的信息代码和控制字符等的差异。
应用层
Application
- 直接为端点用户提供服务。
3.2 TCP/IP四层模型
TCP/IP四层模型 对应OSI七层模型 协议
数据链路层 物理层
数据链路层
IEEE 802.1A, IEEE 802.2到IEEE 802.11
FDDI, Ethernet, Arpanet, PDN, SLIP, PPP
网络层 网络层 IP, ICMP, ARP, RARP, AKP, UUCP
传输层 传输层 TCP, UDP
应用层 会话层
表示层
应用层
Telnet, Rlogin, SNMP, Gopher
SMTP, DNS
HTTP、TFTP, FTP, NFS, WAIS、SMTP
3.3 关于TCP和UDP协议

1)关于TCP协议(Transmission Control Protocol)

  • TCP是一种可靠的、面向连接的传输协议。
  • 传输效率低全双工通信(即同一时刻双向传输)。
  • 面向字节流。
  • 有点类似快递或挂号信,大部分文件传输、浏览器、邮件都使用TCP协议。
    2)关于UDP协议(User Datagram Protocol)
  • UDP协议是一种不可靠的、不面向链接的传输协议。
  • 安全性差,没有发送顺序。
  • 包大小不能超过64kb,但速度快。
  • 类似平邮信,即时通讯比如微信、qq会用到UDP协议。

二、SOCKET编程

1.Socket模块
1.1 Socket模块的常用类方法

1) socket.socket(family,type)

  • 创建并返回socket对象。
  • family表示套接字家族,有两种类型:
家族名 说明
AF_UNIX 基于文件的
AF_INET 基于网络的
  • type表示套接字的种类:
种类 说明
SOCK_STREAM TCP套接字
SOCK_DGRAM UDP套接字
>>>import socket
>>>sock = socket.socket()
>>>print(type(sock))
<class 'socket.socket'>

2) socket.getfqdn(name)

  • 返回完整的主机名。
>>>import socket
>>>sock = socket.getfqdn('127.0.0.1')
>>>print(sock)
DESKTOP-xxxxx

3) socket.gethostbyname(hostname)

  • 返回主机的IP地址。
>>>import socket
>>>sock = socket.gethostbyname('www.baidu.com')
>>>print(sock)
220.181.38.150

4) socket.fromfd(fd, family, type)

  • 从文件描述符创建socket对象。
>>>import socket
>>>sock = socket.socket()
>>>print(sock)
<socket.socket fd=1340, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0>

>>>new_sock = socket.fromfd(sock.fileno(),sock.family,sock.type)
>>>print(new_sock)
<socket.socket fd=1172, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0>
1.2 Socket模块的常用实例方法

1) socket.bind((addres, port))

  • 将socket实例绑定到指定的ip和port上。
>>>import socket
>>>sock = socket.socket()
>>>sock.bind(('127.0.0.1',80))
>>>print(sock)
<socket.socket fd=1344, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 80)>

2) socket.accept()

  • 用于Server端接受Client端的socket。
  • 返回Client端的socket和地址。

3) socket.listen()

  • 使得一个进程可以接受其它进程的请求,从而成为一个服务器进程。

4) socket.connect( (addres, port) )

  • 将socket连接到定义的主机和端口上。

5) socket.recv( buflen[, flags] )

  • 从socket中接收数据,最多buflen个字符。

6) socket.recvfrom( buflen[, flags] )

  • 从 socket 中接收数据,最多 buflen 个字符,同时返回数据来源的远程主机和端口号。

7) socket.send( data[, flags] )

  • 通过socket发送数据

8) socket.send( data[, flags] ,addr)

  • 通过 socket 发送数据到指定地址。

9) socket.close()

  • 关闭socket。

10) socket.getsockopt( lvl, optname )

  • 获得指定socket的值。

11) socket.setsockopt( lvl, optname ,val)

  • 设置指定 socket 选项的值。
>>>#Client端
>>>import socket
>>>sock = socket.socket()
>>>sock.connect(("127.0.0.1",10005)) # 连接服务器
>>>sock.send(b"from client...") # 发送
>>>ret = sock.recv(1024) # 接收
>>>print(ret)
>>>sock.close() # 关闭套接字
b'from server...'

>>>#Server端
>>>import socket
>>>sock = socket.socket()
>>>sock.bind(("127.0.0.1",10005))
>>>sock.listen() # 监听sock
>>>conn,addr = sock.accept() # 接受客户端socket
>>>ret = conn.recv(1024) # 接受客户端信息
>>>print(ret)
>>>conn.send(b'from server...') # 向客户端发送信息
>>>print('Client Socket : ',conn)
>>>print('Client Address:',addr)
>>>conn.close() # 关闭客户端socket
>>>sock.close() # 关闭服务器socket
b'from client...'
Client Socket :  <socket.socket fd=484, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 10005), raddr=('127.0.0.1', 58698)>
Client Address: ('127.0.0.1', 58698)
2.基于UDP协议的Socket编程

1) Server端需要完成的任务

  • 建立Socket实例。
  • 为Socket实例绑定ip和port。
  • 接收Client端的访问。
  • 反馈信息(如果需要)。
#Server端
>>>import socket

>>># 服务器函数
>>>def server_sample():
>>>    # 1.建立socket对象
>>>    sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
>>>    addr = ("127.0.0.1",10005)

>>>    # 2.绑定地址
>>>    sock.bind(addr)

>>>    # 3.接收消息
>>>    data,addr = sock.recvfrom(1024)
>>>    text = data.decode() # 数据流解码
>>>    print(text)

>>>    # 4.返回消息
>>>    rsp = b"from serer..."
>>>    sock.sendto(rsp,addr)
>>>    sock.close()

>>>if __name__ == '__main__':
>>>    print("启动服务器...")
>>>    server_sample()
>>>    print("关闭服务器...")
启动服务器...
from client...
关闭服务器...

2) Client端需要完成的任务

  • 建立Socket实例。
  • 发送内容到Server端。
  • 接收Server端的反馈(如果有)。
#Client端
>>>import socket

>>>def client_sample():
>>>    # 建立socket实例
>>>    sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

>>>    # 发送内容到Server端
>>>    data = b'from client...'
>>>    sock.sendto(data,("127.0.0.1",10005))

>>>    # 接收Server端反馈
>>>    reply,addr = sock.recvfrom(1024)
>>>    text = reply.decode()
>>>    print(text)
>>>    sock.close()

>>>if __name__ == '__main__':
>>>    client_sample()
from serer...
3.基于TCP协议的Socket编程

1) Server端需要完成的任务

  • 建立Socket实例,此实例仅用于接收请求。
  • 为Socket实例绑定ip和port。
  • 监听接入的Socket。
  • 接受Client端访问的Socket,建立通讯链接通路。
  • 使用Client端Socket接收内容
  • 反馈信息(如果需要)。
  • 关闭链接通路。
>>># Server端
>>>import socket

>>>def server_sample():
>>>    # 1. 建立socket实例
>>>    sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

>>>    # 2. 绑定地址
>>>    addr = ("127.0.0.1",10005)
>>>    sock.bind(addr)

>>>    # 3. 开启监听模式
>>>    sock.listen(5)

>>>    while True:
>>>        # 4.接受访问,建立通讯链路
>>>        connection,address = sock.accept()

>>>        # 5.接受内容,内容解码
>>>        data = connection.recv(1024)
>>>        data = data.decode()
>>>        reply = ("Received {} from {}".format(data,address))

>>>        # 6 发送反馈
>>>        connection.send(reply.encode())
>>>        print(reply)

>>>        # 7.关闭链路
>>>        connection.close()

>>>if __name__ == '__main__':
>>>    print("Start Server...")
>>>    server_sample()
>>>    print("End Server...")
Received from client... from ('127.0.0.1', 62157)

2) Client端需要完成的任务

  • 建立Socket实例。
  • 与Server端建立链接通路。
  • 发送内容到Server端。
  • 接收Server端反馈(如果有)
  • 关闭链接通路
>>>import socket

>>>def client():
>>>    # 1.建立socketobj
>>>    sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

>>>    #2.建立链接
>>>    addr = ("127.0.0.1",10005)
>>>    sock.connect(addr)

>>>    #3.发送内容
>>>    msg = b"from client..."
>>>   sock.send(msg)

>>>    #4.接受反馈
>>>    rst = sock.recv(1024)
>>>    print(rst.decode())

>>>    #5.关闭链路
>>>    sock.close()

>>>if __name__ == '__main__':
>>>    client()
Received from client... from ('127.0.0.1', 62157)
4. 处理多个Client(用户端)
4.1 多进程解决方案
# Linux服务器
# Server端
>>>import os,time,sys,socket

>>>host = '172.21.0.4' 
>>>post = 10005

>>>sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
>>>sock.bind((host,post))
>>>sock.listen(5)

>>>activeChildren = [] # 子进程容器
>>>def replace_children():
>>>    # 移除子进程
>>>    while activeChildren:
>>>        pid,stat = os.waitpid(0,os.WNOHANG)
>>>        if not pid:break
 >>>       activeChildren.remove(pid)

>>>def handle_client(conn):
>>>    # 处理子进程
>>>    time.sleep(5)
>>>    while True:
>>>        data = conn.recv(1024)
>>>        if not data:break
>>>        reply = 'Receive {} at {}'.format(data,time.ctime(time.time()))
>>>        conn.send(reply.encode())
>>>    conn.close()
>>>    os._exit(0) # 如果不退出,每个子进程会在返回后继续运行

>>>def main():
>>>    # 监听接入
>>>    while True:
>>>        print("awaiting connection")
>>>        connection,address = sock.accept()
>>>        print("Server connected by {} at {}".format(address,time.ctime(time.time())))
>>>        replace_children()   
>>>        childPid = os.fork()
>>>        if childPid == 0: 
>>>            handle_client(connection)
>>>        else: 
>>>            activeChildren.append(childPid)

>>>if __name__ == '__main__':
>>>    print("starting server..")  
>>>    main()
>>>    print("stoping server...")
Server connected by ('117.119.102.10', 58962) at Sun Apr 12 18:26:30 2020
awaiting connection
Server connected by ('117.119.102.10', 58968) at Sun Apr 12 18:26:32 2020
awaiting connection
Server connected by ('117.119.102.10', 58970) at Sun Apr 12 18:26:34 2020
awaiting connection
# 本地PC端
>>># Client端
>>>import socket,threading,time

>>>def client():
>>>    sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

>>>    addr = ("123.206.41.120",10005)
>>>    sock.connect(addr)

>>>    msg = b"from client..."
>>>    sock.send(msg)

>>>    rst = sock.recv(1024)
>>>    print(rst.decode())

>>>    sock.close()

>>>if __name__ == '__main__':
>>>    for i in range(3): # 用线程模拟多个Client端
>>>        t = threading.Thread(target=client,args=())
>>>        t.start()
>>>        time.sleep(2)
Receive b'from client...' at Sun Apr 12 18:26:35 2020
Receive b'from client...' at Sun Apr 12 18:26:37 2020
Receive b'from client...' at Sun Apr 12 18:26:39 2020
4.2 多线程解决方案
>>>import time,threading,socket

>>>host='127.0.0.1'
>>>port=10005

>>>sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
>>>sock.bind((host,port))
>>>sock.listen(5)

>>>now = lambda: time.ctime(time.time())

>>>def handle_client(connection):
>>>    time.sleep(5)
>>>    while True:
>>>        data = connection.recv(1024)
>>>        if not data:break
>>>        reply = "got {0} at {1}".format(data,now())
>>>        connection.send(reply.encode())
>>>    connection.close()

>>>def main():
>>>    while True:
>>>        connection,address = sock.accept()
>>>        print('Server connected by {0} at {1}...'.format(address,now()))
>>>        t = threading.Thread(target=handle_client,args=(connection,))
>>>        t.start()

>>>if __name__ == '__main__':
>>>    main()
Server connected by ('127.0.0.1', 54071) at Mon Apr 13 09:34:59 2020...
Server connected by ('127.0.0.1', 54073) at Mon Apr 13 09:35:01 2020...
Server connected by ('127.0.0.1', 54077) at Mon Apr 13 09:35:03 2020...
# Client端
>>>import socket,threading,time

>>>def client():
>>>    sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

>>>    addr = ("127.0.0.1",10005)
>>>    sock.connect(addr)

>>>    msg = b"from client..."
>>>    sock.send(msg)

>>>    rst = sock.recv(1024)
>>>    print(rst.decode())
>>>    sock.close()

>>>if __name__ == '__main__':
>>>    for i in range(3): # 用线程模拟多个Client端
>>>        t = threading.Thread(target=client,args=())
>>>        t.start()
>>>        time.sleep(2)
got b'from client...' at Mon Apr 13 09:35:04 2020
got b'from client...' at Mon Apr 13 09:35:06 2020
got b'from client...' at Mon Apr 13 09:35:08 2020
4.3 socketserver包解决方案
>>>import socketserver,time

>>>host='127.0.0.1'
>>>port=10005
>>>now = lambda: time.ctime(time.time())

>>>class MyClientHandler(socketserver.BaseRequestHandler):
>>>    def handle(self):
>>>        # 处理每个接入的请求
>>>        print('Server connected by {0} at {1}...'.format(self.client_address, now()))
>>>        time.sleep(5)
>>>        while True:
>>>            data = self.request.recv(1024)
>>>            if not data:break
>>>            reply = "got {0} at {1}".format(data, now())
>>>            self.request.send(reply.encode())
>>>        self.request.close()

>>>def main():
>>>    server = socketserver.ThreadingTCPServer((host,port),MyClientHandler)
>>>    server.serve_forever()

>>>if __name__ == '__main__':
>>>    print('Starting server...')
>>>    main()
>>>    print('Stoping Server...')
Starting server...
Server connected by ('127.0.0.1', 60706) at Mon Apr 13 11:22:27 2020...
Server connected by ('127.0.0.1', 60708) at Mon Apr 13 11:22:29 2020...
Server connected by ('127.0.0.1', 60710) at Mon Apr 13 11:22:31 2020...
>>># Client端
>>>import socket,threading,time

>>>def client():
>>>    sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

>>>    addr = ("127.0.0.1",10005)
>>>    sock.connect(addr)

>>>    msg = b"from client..."
>>>    sock.send(msg)

>>>    rst = sock.recv(1024)
>>>    print(rst.decode())
>>>    sock.close()

>>>if __name__ == '__main__':
>>>    for i in range(3): # 用线程模拟多个Client端
>>>        t = threading.Thread(target=client,args=())
>>>        t.start()
>>>        time.sleep(2)
got b'from client...' at Mon Apr 13 11:22:32 2020
got b'from client...' at Mon Apr 13 11:22:34 2020
got b'from client...' at Mon Apr 13 11:22:36 2020
4.4 协程解决方案
>>>import time,asyncio

>>>host='127.0.0.1'
>>>port=10005
>>>now = lambda: time.ctime(time.time())

>>>async def handle_client(reader,writer):
>>>    data = await reader.read(1024)
>>>    message = data.decode()
>>>    address = writer.get_extra_info('peername')
>>>    print('Server connected by {0} at {1}...'.format(address, now()))

>>>    reply = "got {0} at {1}".format(message,now())
>>>    writer.write(reply.encode())
>>>    await writer.drain()

>>>    print('Closing Client:{}'.format(address))
>>>    writer.close()

>>>def main():
>>>    loop = asyncio.get_event_loop() # 创建loop
>>>    task = asyncio.start_server(handle_client,host,port,loop=loop) # 将事件抛到loop中
>>>    server = loop.run_until_complete(task)
>>>    print('serving on {}'.format(server.sockets[0].getsockname()))

>>>    try:
>>>        loop.run_forever()
>>>    except KeyboardInterrupt: # 用Ctrl+c打断服务器
>>>        pass

>>>    server.close()
>>>    loop.run_until_complete(server.wait_closed())
>>>    loop.close()

>>>if __name__ == '__main__':
>>>    print('Starting server...')
>>>    main()
>>>    print('Stoping Server...')
Starting server...
serving on ('127.0.0.1', 10005)
Server connected by ('127.0.0.1', 59093) at Mon Apr 13 10:46:30 2020...
Closing Client:('127.0.0.1', 59093)
Server connected by ('127.0.0.1', 59095) at Mon Apr 13 10:46:32 2020...
Closing Client:('127.0.0.1', 59095)
Server connected by ('127.0.0.1', 59096) at Mon Apr 13 10:46:34 2020...
Closing Client:('127.0.0.1', 59096)
# Client端
>>>import socket,threading,time

>>>def client():
>>>    sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

>>>    addr = ("127.0.0.1",10005)
>>>    sock.connect(addr)

>>>    msg = b"from client..."
>>>    sock.send(msg)

>>>    rst = sock.recv(1024)
>>>    print(rst.decode())

>>>    sock.close()

>>>if __name__ == '__main__':
>>>    for i in range(3): # 用线程模拟多个Client端
>>>        t = threading.Thread(target=client,args=())
>>>        t.start()
>>>        time.sleep(2)
got from client... at Mon Apr 13 10:46:30 2020
got from client... at Mon Apr 13 10:46:32 2020
got from client... at Mon Apr 13 10:46:34 2020
4.5 select包 I/O多路复用解决方案
参数 含义
rlist 可读集合
wlist 可写集合
xlist 异常集合
timeout 等待期限
0:立即返回
省略:等待至少一个对象准备好。
>>>import time,socket
>>>from select import select

>>>def main():
>>>    host = '127.0.0.1'
>>>    port = 10005
>>>    now = lambda: time.ctime(time.time())
>>>    num_socks = 3  # 允许的接入数量

>>>    mainsocks,readsocks,writesocks = [],[],[]
>>>    for i in range(num_socks):
>>>        # 建立一个连接
>>>        portsock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
>>>        portsock.bind((host,port))
>>>        portsock.listen(5)
>>>        # 将连接放到列表中
>>>        mainsocks.append(portsock)
>>>        readsocks.append(portsock)
>>>        port += 1

>>>    print('loop starting...')
>>>    while True:
>>>        readables,writeables,exceptions = select(readsocks,writesocks,[])
>>>        for sock in readables:
>>>          if sock in mainsocks: # 如果sock已经准备好
>>>                # 如果是新的接入
>>>                newsock,address = sock.accept()
>>>                print('Server connected by {0} at {1}...'.format(address, now()))
>>>                readsocks.append(newsock) # 加入到已读列表
>>>            else:
>>>                # 如果是池子中的连接
>>>                data = sock.recv(1024)
>>>                if not data:
>>>                    sock.close()
>>>                    readsocks.remove(sock)
>>>                else:
>>>                    # 可能会阻塞的部分
>>>                    reply = "got {0} at {1}".format(data, now())
>>>                    sock.send(reply.encode())

>>>if __name__ == '__main__':
>>>    main()
loop starting...
Server connected by ('127.0.0.1', 56875) at Mon Apr 13 14:49:33 2020...
Server connected by ('127.0.0.1', 56877) at Mon Apr 13 14:49:35 2020...
Server connected by ('127.0.0.1', 56879) at Mon Apr 13 14:49:37 2020...
>>># Client端
>>>import socket,threading,time

>>>def client():
>>>    sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

>>>    addr = ("127.0.0.1",10005)
>>>    sock.connect(addr)

>>>    msg = b"from client..."
>>>    sock.send(msg)

>>>    rst = sock.recv(1024)
>>>    print(rst.decode())

>>>    sock.close()

>>>if __name__ == '__main__':
>>>    for i in range(3): # 用线程模拟多个Client端
>>>        t = threading.Thread(target=client,args=())
>>>        t.start()
>>>        time.sleep(2)
got b'from client...' at Mon Apr 13 14:49:33 2020
got b'from client...' at Mon Apr 13 14:49:35 2020
got b'from client...' at Mon Apr 13 14:49:37 2020
5. Socket流的重定向
>>>import time,sys,socket

>>>host='127.0.0.1'
>>>port=10005

>>>sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
>>>sock.bind((host,port))
>>>sock.listen(1)

>>>now = lambda: time.ctime(time.time())

>>>def handle_client(connection):
>>>    time.sleep(5)
>>>    while True:
>>>        file = connection.makefile('r') # 将输入流关联到file
>>>        data = file.readline().rstrip() # 读取第一行
>>>        if not data:break
>>>        reply = "got {0} at {1}".format(data,now())
>>>        connection.send(reply.encode())
>>>    connection.close()

>>>def main():
>>>    while True:
>>>        connection,address = sock.accept()
>>>        print('Server connected by {0} at {1}...'.format(address, now()))
>>>        handle_client(connection)

>>>if __name__ == '__main__':
>>>    print('starting server...')
>>>    main()
>>>    print('stoping server...')
starting server...
Server connected by ('127.0.0.1', 56127) at Mon Apr 13 16:19:18 2020...
>>># Client端
>>>import socket,sys,time

>>>host = "127.0.0.1"
>>>port = 10005
>>>sysout = sys.stdout # 备份输出流

>>>def client():
>>>    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>>    sock.connect((host, port))

>>>    # 将输出流导入file
>>>    file = sock.makefile('w')
>>>    sys.stdout = file

>>>    msg = b"from client..."
>>>    print(msg)
>>>    sys.stdout.flush() # 闪现缓存

>>>    sys.stdout = sysout # 将输出流恢复默认
>>>    rst = sock.recv(1024)
>>>    print(rst.decode())

>>>    sock.close()

>>>if __name__ == '__main__':
>>>    client()
got b'from client...' at Mon Apr 13 16:19:23 2020

参考资料



本文作者:大师兄(superkmi)

上一篇 下一篇

猜你喜欢

热点阅读