网络编程(三)

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

循环通信:

  存在的问题,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()
server端
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()
client端

连接循环:

  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端会一直运行
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()
client端
('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()
server端
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()
client端

黏包现象:只有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()
server端
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()
client端

执行命令:ipconfig/all

执行命令:dir

执行命令:dir

执行命令:d

ipconfig/all
2594
dir
382
dir
382
d
60
运行结果server端
>>>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 可用字节

>>>
运行结果client端

第二种情况:发送端需要等缓冲区才发送出去,造成粘包(发送数据时间间隔太短,数据也很小,会合到一起,产生粘包)

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()
server端
import socket
sk=socket.socket()
sk.connect(('127.0.0.1',8888))

sk.send(b'hello')
sk.send(b'world')

sk.close()
clinet端
b'helloworld'
b''
运行结果

 

posted @ 2019-02-20 18:59  烧刘病  阅读(263)  评论(0编辑  收藏  举报
回到页首