• 8-2udp和tcp网络编程以及粘包和解决粘包的方法


    一  tcp网络编程

     1 server 端
     2 
     3 import socket
     4 sk=socket.socket()  #实例化一个对象
     5 sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)#端口可以重用
     6 sk.bind(('127.0.0.1',9100))
     7 sk.listen()#监听
     8 while True:
     9     conn,addr=sk.accept() #阻塞,三次握手完毕
    10     while True:
    11         inp=input('请输入你要发送的消息:')
    12         conn.send(inp.encode('utf-8'))
    13         if inp == 'q': break
    14         ret=conn.recv(1024).decode('utf-8')
    15         if ret == 'q': break
    16         print(ret)
    17 
    18     conn.close()
    19 sk.close()
      client端
    1
    import socket 2 sk=socket.socket() 3 #while True: 4 sk.connect(('127.0.0.1',9100)) 5 while True: 6 ret=(sk.recv(1024).decode('utf-8')) 7 if ret == 'q': break 8 print(ret) 9 inp=input('请输入你要发送的消息:') 10 sk.send(inp.encode('utf-8')) 11 if inp == 'q': break 12 13 sk.close()

    二 tcp粘包

    1  发送方的缓存机制

    发送数据时间间隔很短,数据了很小,会合到一起,产生粘包

     1 服务端
     2 #_*_coding:utf-8_*_
     3 from socket import *
     4 ip_port=('127.0.0.1',8080)
     5 
     6 tcp_socket_server=socket(AF_INET,SOCK_STREAM)
     7 tcp_socket_server.bind(ip_port)
     8 tcp_socket_server.listen(5)
     9 
    10 
    11 conn,addr=tcp_socket_server.accept()
    12 
    13 
    14 data1=conn.recv(10)
    15 data2=conn.recv(10)
    16 
    17 print('----->',data1.decode('utf-8'))
    18 print('----->',data2.decode('utf-8'))
    19 
    20 conn.close()
    21 
    22 服务端
    服务端
     1 #_*_coding:utf-8_*_
     2 import socket
     3 BUFSIZE=1024
     4 ip_port=('127.0.0.1',8080)
     5 
     6 s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
     7 res=s.connect_ex(ip_port)
     8 
     9 
    10 s.send('hello'.encode('utf-8'))
    11 s.send('egg'.encode('utf-8'))
    客户端

    2接收方的缓存机制

    客户端发送了一段数据,服务端只收了一小部分,服务端下次再收的时候还是从缓冲区拿上次遗留的数据,产生粘包) 

     1 #_*_coding:utf-8_*_
     2 from socket import *
     3 ip_port=('127.0.0.1',8080)
     4 
     5 tcp_socket_server=socket(AF_INET,SOCK_STREAM)
     6 tcp_socket_server.bind(ip_port)
     7 tcp_socket_server.listen(5)
     8 
     9 
    10 conn,addr=tcp_socket_server.accept()
    11 
    12 
    13 data1=conn.recv(2) #一次没有收完整
    14 data2=conn.recv(10)#下次收的时候,会先取旧的数据,然后取新的
    15 
    16 print('----->',data1.decode('utf-8'))
    17 print('----->',data2.decode('utf-8'))
    18 
    19 conn.close()
    服务端
     1 #_*_coding:utf-8_*_
     2 import socket
     3 BUFSIZE=1024
     4 ip_port=('127.0.0.1',8080)
     5 
     6 s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
     7 res=s.connect_ex(ip_port)
     8 
     9 
    10 s.send('hello egg'.encode('utf-8'))
    客户端

    三 解决粘包问题

     1 import socket
     2 import struct
     3 sk=socket.socket()
     4 sk.bind(('127.0.0.1',8090))
     5 sk.listen()
     6 conn,addr=sk.accept()
     7 inp=input('>>>:').encode('utf-8')
     8 inp_len=len(inp)#计算用户输入的长度
     9 bytes_msg=struct.pack('i',inp_len)#将数字转换成固定的bytes
    10 conn.send(bytes_msg) #先发送报头的长度4个bytes
    11 conn.send(inp)#在发送报头的字节格式
    12 conn.send(b'alex sb')#最后发送真实内容的字节格式
    13 conn.close()
    14 sk.close()
    服务端
     1 import socket
     2 import struct
     3 sk=socket.socket()
     4 sk.connect(('127.0.0.1',8090))
     5 num=sk.recv(4) #先接受bytes的长度
     6 num=struct.unpack('i',num)[0]#提取报文的长度
     7 print(sk.recv(num).decode('utf-8'))
     8 print(sk.recv(10))
     9 
    10 sk.close()
    客户端

    四 udp

     1 udp server端
     2 
     3 import socket
     4 sk=socket.socket(type=socket.SOCK_DGRAM)
     5 sk.bind(('127.0.0.1',8899))
     6 while True:
     7     msg,addr=sk.recvfrom(1024)
     8     print(msg.decode('utf-8'),addr)
     9     inp=input('>>>:')
    10     if inp=='q':break
    11     sk.sendto(inp.encode('utf-8'),addr)
    12     #print(msg)
    13 sk.close()
     1 udp client
     2 
     3 import socket
     4 sk=socket.socket(type=socket.SOCK_DGRAM)
     5 sk.bind(('127.0.0.1',8899))
     6 while True:
     7     msg,addr=sk.recvfrom(1024)
     8     print(msg.decode('utf-8'),addr)
     9     inp=input('>>>:')
    10     if inp=='q':break
    11     sk.sendto(inp.encode('utf-8'),addr)
    12     #print(msg)
    13 sk.close()
  • 相关阅读:
    C#设计模式之单例模式(Singleton Pattern)
    ASP.NET MVC Route之WebForm路由与源码分析(二)
    ASP.NET MVC Route之WebForm路由与源码分析(一)
    Autofac初探(一)
    Razor基础语法一
    ASP.NET MVC之视图传参到控制器的几种形式
    LINQ to SQL语句(2)Count/Sum/Min/Max/Avg操作符
    LINQ to SQL语句(1)Select查询的九种形式
    学习《深入理解C#》—— 泛型 (第三章3.1---3.2)
    学习《深入理解C#》—— 委托的构成、合并与删除和总结 (第二章1.1---1.4)
  • 原文地址:https://www.cnblogs.com/huningfei/p/9117521.html
Copyright © 2020-2023  润新知