socket套接字

Posted daviddd

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了socket套接字相关的知识,希望对你有一定的参考价值。

socket

1,定义

  1. 套接字
    1. 基于tcp协议
    2. socket是基于应用层与传输层之间的抽象层,是一组操作起来非常简单的接口,接收应用层的数据,然后传给操作系统
  2. 分类:
    1. 基于文件类型的套接字家族:AF-UNIX,不常用
    2. 基于网络类型的套接字家族:AF-INET
  3. 模块语法
    1. shell:命令解释器,相当于调用cmd,执行指定的命令
    2. stdout:正确结果以字符串的形式send个客户端
    3. stderr:错误的结果以字符串的形式send给客户端
    4. windows操作系统的默认编码是gbk

粘包

  1. 粘包的两种方式
    1. 连续短暂的多次send,数据量很小,数据就会统一发出去
    2. send的数据过大,大于对方recv的上限时,对方第一次recv时,会接收上一次没有recv完的剩余数据,这就是粘包
  2. 只有tcp会粘包,udp永远不会粘包,粘包现象的发生于缓冲区有关系
  3. 缓存区
    1. 暂时储存一些数据
    2. 缓存取得存在,避免了网络波动等影响对数据传输的影响,保证了数据的收发稳定,匀速
    3. 缺点:就是照成了粘包现象
  4. 解决粘包现象
    1. 发送数据长度,客服端循环接收数据知道接收完数据
    2. 自定义报头

ftp协议

1,文件传输协议

  1. FTP使用两个并行的TCP连接来传输文件,一个是控制连接(用于在两主机之间传递控制信息),一个是数据连接(用于实际传输一个文件)。因为FTP协议使用一个分离的控制连接,所以我们也称FTP的控制信息是带外传送的
  2. 自定制报头
  3. 可以解觉文件过大的问题

2,服务端要点

自定义报头                                                                  
head_dic = {"filename":"文件名",                                            
            "md5":11111111111,                                           
            "size":total_size}                                
json形式的报头
head_dic_json = json.dumps(head_dic)

bytes形式报头
head_dic_json_bytes = head_dic_json.encoude('utf-8')

bytes长度
len_head = len(head_dic_json_bytes)

将不固定的int总字节数转换成固定长度的4个字节
head_size = struct.pack('i',len_head)

发送固定字节
conn.send(head_size)

发送字典的bytes数据
conn.send(head_dic_json_size)

发送总数据(result)

                                  

3,客户端要点

接收4个固定字节的报头
from_server_data = client.recv(4)

将接收到的4个字节的固定报头翻转会字典的bytes长度
len_dic_size = struct.unpack('i',from_server_data)

通过翻转的长度接收字典的bytes数据
dic_bytes = client.recv(len_dic_size)

将bytes类型装换成json类型的字典
dic_json = dic_bytes.decode('utf-8')

json反序列化成原字典
dic = json.loads(dic_json)

得到原字典就得到了源数据的总字节数
total_size = dic["size"]

udp

  1. 服务端

    1. 基于udp协议的socket无序建立管道,先开启服务端或者客户端都行
    2. 基于udp协议的socket接收一个消息,与发送一个消息都是无连接的
    3. 只要拿到我都IP地址和端口就可以给我发消息,我按照顺序接收消息
    import socket
    server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    # 基于网络的UDP协议的socket
    server.bind(('192.168.14.198',9000))
    
    while 1:
    
        from_client_data = server.recvfrom(1024)  # 阻塞,等待客户来消息
        print(f'33[1;35;0m来自客户端{from_client_data[1]}: {from_client_data[0].decode("utf-8")} 33[0m')
        # to_client_data = input('>>>').strip()
        # server.sendto(to_client_data.encode('utf-8'),from_client_data[1])
    

2,client端

  • ? udp

    • import socket
      client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
      # 基于网络的UDP协议的socket
      
      while 1:
      
          to_server_data = input('>>>:').strip()
          client.sendto(to_server_data.encode('utf-8'),('127.0.0.1',9000))
          # data,addr = client.recvfrom(1024)
          # print(f'来自服务端{addr}消息:{data.decode("utf-8")}')

以上是关于socket套接字的主要内容,如果未能解决你的问题,请参考以下文章

19 网络编程--Socket 套接字方法

.Net Socket 类错误代码

片段和活动之间的核心区别是啥?哪些代码可以写成片段?

socket(套接字)

Socket.io 向套接字发送消息时出错

socket_recv():无法从socket [0]读取:操作成功完成