网络编程 06.27

1.粘包问题

tcp协议才会有粘包问题,udp协议没有粘包问题

粘包问题的几种情况:

  1. D1 和D2间隔时间长,两者数据量小,不会发生粘包问题
  2. D1和D2间隔时间非常短,数据量小,会发生粘包问题
  3. D2比较大,D1比较小,间隔时间也短,服务端一次性读取D1和D2的一部分,出现了粘包问题
  4. D1大,D2比较小,获取D1的一部分,然后获取了D1的剩余部分和D2,出现了粘包问题

解决方案:

  • 两者间隔时间边长
  • 发送之前告诉客户端数据的大小,大小的位置必须得固定。

2.解决粘包问题

#tcp服务端.py
import socket
import struct
import subprocess
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(('127.0.0.1',8000))
server.listen(5)
print('start...')
while True:
	conn, client_address = server.accept()
    print(client_address)
    while True:
        try:
            cmd = conn.recv(1024)
            print(cmd)
            pipeline = subprocess.Popen(cmd.decode('utf8'),
                                       shell=True,           
                                       			        stderr=subprocess.PIPE,														                 stdout=subprocess.PIPE)
			stdout = pipeline.stdout.read()
			stderr = pipeline.stderr.read()

			count_len = len(stdout)+len(stderr)
			guding_bytes = struct.pack('i',count_len)

			conn.send(guding_bytes)
			conn.send(stderr + stdout)
          except ConnectionResetError:
            break
      conn.close
    
#tcp客户端.py
import struct
from socket import *
client = socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8000))
while True:
    cmd = 'dir'
    client.send(cmd.encode('utf8'))
    guding_bytes = client.recv(4)
    count_len = struct.unpack('i',guding_bytes)[0]
    data = client.recv(count_len)
    print(data.decode('gbk'))

3.UDP套接字简单示例

#udp服务端.py
import socket
server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
server.bind(('127.0.0.1',8000))
print('start...')
while True:
    data, client_addr = server.recvfrom(1024)
    print(client_addr)
    print(data)
    server.sendto(data.upper(),client_addr)
    
#udp客户端.py
import socket
client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
while True:
    msg = input('please enter your msg')
    client.sendto(msg.encode('utf8'),('127.0.0.1',8000))
    data = client.recvfrom(1024)
    print(data)
  • UDP是无链接的,先启动哪一端都不会报错
  • UDP协议是数据报协议,发空的时候也会自带报头,因此客户端输入空,服务端也能收到
  • UPD协议一般不用于传输大数据。
  • UDP套接字虽然没有粘包问题,但是不能替代TCP套接字,因为UPD协议有一个缺陷:如果数据发送的途中,数据丢失,则数据就丢失了,而TCP协议则不会有这种缺陷,因此一般UPD套接字用户无关紧要的数据发送,例如qq聊天。

4.基于socketservver实现并发的socket套接字编程

#服务端.py
import socketserver
import subprocess
import struct


class MyHandler(socketserver.BaseRequestHandler):
    # 通信循环
    def handle(self):

        while True:
            try:
                cmd = self.request.recv(1024)
                print(cmd)

                pipeline = subprocess.Popen(cmd.decode('utf8'),
                                            shell=True,
                                            stderr=subprocess.PIPE,
                                            stdout=subprocess.PIPE)

                stdout = pipeline.stdout.read()
                stderr = pipeline.stderr.read()

                count_len = len(stdout) + len(stderr)
                guding_bytes = struct.pack('i', count_len)

                self.request.send(guding_bytes)  # 4

                self.request.send(stderr + stdout)

            except ConnectionResetError:
                break


# 使用socketserver的连接循环(并发),但是使用了自己的通信循环
# myhandler = MyHandler()
                    
if __name__ == '__main__':
    s = socketserver.ThreadingTCPServer(('127.0.0.1', 8080), MyHandler, bind_and_activate=True)
    s.serve_forever()

#客户端.py
import socket
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connet(('127.0.0.1',8000))
while True:
    msg = input(please enter your msg ).strip()
    msg = 'client'
    if len(msg) == 0: continue
        client.send(msg.encode('utf8'))
        data =client.recv(1024)
        print(data)
   
#客户端1.py
import socket
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connet(('127.0.0.1',8000))
while True:
    msg = input(please enter your msg ).strip()
    msg = 'client'
    if len(msg) == 0: continue
        client.send(msg.encode('utf8'))
        data =client.recv(1024)
        print(data)
        
#客户端2.py
import socket
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connet(('127.0.0.1',8000))
while True:
    msg = input(please enter your msg ).strip()
    msg = 'client'
    if len(msg) == 0: continue
        client.send(msg.encode('utf8'))
        data =client.recv(1024)
        print(data)
posted @ 2019-06-27 19:32  海森t  阅读(49)  评论(0)    收藏  举报