网络编程(三)
基于tcp的socket通信
简单通信
循环通信
连接循环
远程操作命令
粘包现象
简单通信:
import socket sk=socket.socket() sk.bind(('127.0.0.1',8888)) sk.listen(5) conn,addr=sk.accept() ret=conn.recv(1024) print(ret.decode('utf-8')) conn.send(ret+b'sb') conn.close() sk.close()
import socket sk=socket.socket() sk.connect(('127.0.0.1',8888)) msg=input('>>>') sk.send(msg.encode('utf-8')) ret=sk.recv(1024) print(ret.decode('utf-8')) sk.close()
循环通信:
存在的问题,server端一直在运行的情况下,
client端正常关闭,非正常关闭
import socket sk=socket.socket() sk.bind(('127.0.0.1',8888)) sk.listen(5) conn,addr=sk.accept() while 1: try: ret=conn.recv(1024) print(ret.decode('utf-8')) conn.send(ret+b'sb') except Exception: break conn.close() sk.close()
import socket sk=socket.socket() sk.connect(('127.0.0.1',8888)) while 1: msg=input('>>>') if msg=='q':break sk.send(msg.encode('utf-8')) ret=sk.recv(1024) print(ret.decode('utf-8')) sk.close()
连接循环:
server端一直运行(不能实现并发)
实现多个client对话功能。(必须在一个client端关闭之后之后的才能启动)
import socket sk=socket.socket() sk.bind(('127.0.0.1',8888)) sk.listen(5) while 1: conn,addr=sk.accept() print(addr) while 1: try: ret=conn.recv(1024) print(ret.decode('utf-8')) conn.send(ret+b'sb') except Exception: break conn.close()#当client关闭执行 sk.close()#不会执行,server端会一直运行
import socket sk=socket.socket() sk.connect(('127.0.0.1',8888)) while 1: msb=input('>>>') if msb=='q':break sk.send(msb.encode('utf-8')) ret=sk.recv(1024) print(ret.decode('utf8')) sk.close()
('127.0.0.1', 61382) a ('127.0.0.1', 61384) a ('127.0.0.1', 61386) a bs
远程操作命令:
import socket import subprocess sk=socket.socket() sk.bind(('127.0.0.1',8888)) sk.listen(5) conn,addr=sk.accept() while 1: try: ret=conn.recv(1024) ret=ret.decode('utf-8') print(ret) obj=subprocess.Popen(ret, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout_data=obj.stdout.read()#结果是字节 stderr_data=obj.stderr.read() data=stdout_data+stderr_data print(len(data))#dir 命令 382 conn.send(stdout_data+stderr_data) except Exception: break conn.close() sk.close()
import socket sk=socket.socket() sk.connect(('127.0.0.1',8888)) while 1: msg=input('>>>') if msg=='q':break sk.send(msg.encode('utf-8')) ret=sk.recv(1024) print(ret.decode('gbk')) sk.close()
黏包现象:只有TCP存在黏包现象,UDP不会有
1.一次发送的数据超过1024(最大限制字节),他会在执行下一次命令的时候把上一次没显示完的数据显示出来
(原因:只要send就会立马recv数据(上次未读完的数据))
2.同时多次send数据,会一次性recv到数据。
第一种情况:
接收方没有及时接收缓冲区的包,造成多个包接收(客户端发送了一段数据,服务端之收了一小部分,服务端下次在收的时候还是从缓冲区拿上次遗留的数据,产生粘包)


import socket import subprocess sk=socket.socket() sk.bind(('127.0.0.1',8888)) sk.listen(5) conn,addr=sk.accept() while 1: try: ret=conn.recv(1024) ret=ret.decode('utf-8') print(ret) obj=subprocess.Popen(ret, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout_data=obj.stdout.read()#结果是字节 stderr_data=obj.stderr.read() data=stdout_data+stderr_data print(len(data))#dir 命令 382 conn.send(stdout_data+stderr_data) except Exception: break conn.close() sk.close()
import socket sk=socket.socket() sk.connect(('127.0.0.1',8888)) while 1: msg=input('>>>') if msg=='q':break sk.send(msg.encode('utf-8')) ret=sk.recv(1024) print(ret.decode('gbk')) sk.close()
执行命令:ipconfig/all
执行命令:dir
执行命令:dir
执行命令:d
ipconfig/all 2594 dir 382 dir 382 d 60
>>>ipconfig/all Windows IP 配置 主机名 . . . . . . . . . . . . . : LAPTOP-BPOBFM1M 主 DNS 后缀 . . . . . . . . . . . : 节点类型 . . . . . . . . . . . . : 混合 IP 路由已启用 . . . . . . . . . . : 否 WINS 代理已启用 . . . . . . . . . : 否 无线局域网适配器 本地连接* 3: 媒体状态 . . . . . . . . . . . . : 媒体已断开连接 连接特定的 DNS 后缀 . . . . . . . : 描述. . . . . . . . . . . . . . . : Microsoft Wi-Fi Direct Virtual Adapter #2 物理地址. . . . . . . . . . . . . : B8-81-98-00-25-0E DHCP 已启用 . . . . . . . . . . . : 是 自动配置已启用. . . . . . . . . . : 是 无线局域网适配器 本地连接* 4: 媒体状态 . . . . . . . . . . . . : 媒体已断开连接 连接特定的 DNS 后缀 . . . . . . . : 描述. . . . . . . . . . . . . . . : Microsoft Wi-Fi Direct Virtual Adapter #3 物理地址. . . . . . . . . . . . . : BA-81-98-00-25-0D DHCP 已启用 . . . . . . . . . . . : 是 自动配置已启用. . . . . . . . . . : 是 以太网适配器 SSTAP 1: 媒体状态 . . . . . . . . . . . >>>dir . : 媒体已断开连接 连接特定的 DNS 后缀 . . . . . . . : 描述. . . . . . . . . . . . . . . : TAP-Windows Adapter V9 物理地址. . . . . . . . . . . . . : 00-FF-6A-01-8A-5E DHCP 已启用 . . . . . . . . . . . : 是 自动配置已启用. . . . . . . . . . : 是 以太网适配器 以太网 2: 连接特定的 DNS 后缀 . . . . . . . : 描述. . . . . . . . . . . . . . . : ASIX AX88772C USB2.0 to Fast Ethernet Adapter 物理地址. . . . . . . . . . . . . : 00-0E-C6-B4-39-19 DHCP 已启用 . . . . . . . . . . . : 是 自动配置已启用. . . . . . . . . . : 是 本地链接 IPv6 地址. . . . . . . . : fe80::4081:efe4:7601:6631%5(首选) IPv4 地址 . . . . . . . . . . . . : 192.168.16.155(首选) 子网掩码 . . . . . . . . . . . . : 255.255.255.0 获得租约的时间 . . . . . . . . . : 2019年2月20日 8:18:14 租约过期的时间 . . . . . . . . . : 2019年2月20日 23:11:24 默认网关. . . . . . . . . . . . . : 192.168.16.1 DHCP 服务器 . . . . . . . . . . . : 192.168.16.2 DHCPv6 IAID . . . . . . . . . . >>>dir . : 855641798 DHCPv6 客户端 DUID . . . . . . . : 00-01-00-01-1F-FA-C2-52-B8-81-98-00-25-0D DNS 服务器 . . . . . . . . . . . : 119.29.29.29 TCPIP 上的 NetBIOS . . . . . . . : 已禁用 无线局域网适配器 WLAN: 媒体状态 . . . . . . . . . . . . : 媒体已断开连接 连接特定的 DNS 后缀 . . . . . . . : Home 描述. . . . . . . . . . . . . . . : Intel(R) Dual Band Wireless-AC 3165 物理地址. . . . . . . . . . . . . : B8-81-98-00-25-0D DHCP 已启用 . . . . . . . . . . . : 是 自动配置已启用. . . . . . . . . . : 是 驱动器 D 中的卷是 LENOVO 卷的序列号是 62FE-3C4F D:\python-file\python全栈\day28\04远程操作系统命令 的目录 2019-02-20 20:41 <DIR> . 2019-02-20 20:41 <DIR> .. 2019-02-20 20:32 223 client.py 2019-02-20 20:41 693 sever.py 2 个文件 916 字节 2 个目录 68,353,490,944 可用字节 >>>d 驱动器 D 中的卷是 LENOVO 卷的序列号是 62FE-3C4F D:\python-file\python全栈\day28\04远程操作系统命令 的目录 2019-02-20 20:41 <DIR> . 2019-02-20 20:41 <DIR> .. 2019-02-20 20:32 223 client.py 2019-02-20 20:41 693 sever.py 2 个文件 916 字节 2 个目录 68,353,490,944 可用字节 >>>
第二种情况:发送端需要等缓冲区才发送出去,造成粘包(发送数据时间间隔太短,数据也很小,会合到一起,产生粘包)

import socket sk=socket.socket() sk.bind(('127.0.0.1',8888)) sk.listen(5) conn,addr=sk.accept() data1=conn.recv(1024) print(data1) data2=conn.recv(1024) print(data2) conn.close() sk.close()
import socket sk=socket.socket() sk.connect(('127.0.0.1',8888)) sk.send(b'hello') sk.send(b'world') sk.close()
b'helloworld' b''

浙公网安备 33010602011771号