• Python网络编程—socket套接字编程(TCP)


    套接字介绍

    1.套接字 : 实现网络编程进行数据传输的一种技术手段

    2.Python实现套接字编程:import socket

    3.套接字分类

    • 流式套接字(SOCK_STREAM): 以字节流方式传输数据,实现tcp网络传输方案。(面向连接--tcp协议--可靠的--流式套接字)
    • 数据报套接字(SOCK_DGRAM):以数据报形式传输数据,实现udp网络传输方案。(无连接--udp协议--不可靠--数据报套接字)

    tcp套接字

    服务端流程

    1.创建套接字

    sockfd=socket.socket(socket_family=AF_INET,socket_type=SOCK_STREAM,proto=0)

    • 功能:创建套接字
    • 参数: socket_family 网络地址类型 AF_INET表示ipv4
    •     socket_type 套接字类型 SOCK_STREAM(流式) SOCK_DGRAM(数据报)
    •     proto 通常为0 选择子协议
    • 返回值: 套接字对象

    2.绑定地址

    本地地址 : 'localhost' , '127.0.0.1'
    网络地址 : '172.40.91.185'
    自动获取地址: '0.0.0.0'

    sockfd.bind(addr)

    • 功能: 绑定本机网络地址
    • 参数: 二元元组 (ip,port) ('0.0.0.0',8888)

    3.设置监听

    sockfd.listen(n)

    • 功能 : 将套接字设置为监听套接字,确定监听队列大小
    • 参数 : 监听队列大小

    4.等待处理客户端连接请求

    connfd,addr = sockfd.accept()

    • 功能: 阻塞等待处理客户端请求
    • 返回值: connfd 客户端连接套接字
    •     addr 连接的客户端地址

    5.消息收发

    data = connfd.recv(buffersize)

    • 功能 : 接受客户端消息
    • 参数 :每次最多接收消息的大小
    • 返回值: 接收到的内容

    n = connfd.send(data)

    • 功能 : 发送消息
    • 参数 :要发送的内容 bytes格式
    • 返回值: 发送的字节数

    6.关闭套接字

    sockfd.close()

    • 功能:关闭套接字
    tcp服务端流程

    客户端流程

    1.创建套接字

    注意:只有相同类型的套接字才能进行通信

    2.请求连接

    sockfd.connect(server_addr)

    • 功能:连接服务器
    • 参数:元组 服务器地址

    3.收发消息

    注意: 防止两端都阻塞,recv send要配合

    4.关闭套接字

     1 """
     2 重点代码
     3 """
     4 
     5 from socket import *
     6 
     7 # 创建tcp套接字
     8 sockfd = socket() # 参数默认即tcp套接字
     9 
    10 # 连接服务端程序
    11 server_addr = ("172.40.91.150",8888)  # 服务端地址
    12 sockfd.connect(server_addr)
    13 
    14 while True:
    15   # 消息发送接收
    16   data = input("Msg>>")
    17   # 如果直接回车,则跳出循环
    18   if not data:
    19     break
    20   sockfd.send(data.encode()) # 转换字节串发送
    21   data = sockfd.recv(1024)
    22   print("Server:",data.decode())
    23 
    24 sockfd.close()
    tcp客户端流程

    tcp 套接字数据传输特点

    • tcp连接中当一端退出,另一端如果阻塞在recv,此时recv会立即返回一个空字串。
    • tcp连接中如果一端已经不存在,仍然试图通过send发送则会产生BrokenPipeError
    • 一个监听套接字可以同时连接多个客户端,也能够重复被连接

    网络收发缓冲区

    • 网络缓冲区有效的协调了消息的收发速度
    • send和recv实际是向缓冲区发送接收消息,当缓冲区不为空recv就不会阻塞。

    tcp粘包

    代码示例:day2/stick_send.py,stick_recv.py

    原因:tcp以字节流方式传输,没有消息边界。多次发送的消息被一次接收,此时就会形成粘包。

    影响:如果每次发送内容是一个独立的含义,需要接收端独立解析此时粘包会有影响。

    处理方法:

    • 人为的添加消息边界
    • 控制发送速度
     1 from socket import *
     2 
     3 
     4 sockfd = socket()
     5 
     6 server_addr = ("172.40.91.150",8888)
     7 sockfd.connect(server_addr)
     8 
     9 while True:
    10   sockfd.send(b'hello')
    11 
    12 sockfd.close()
    tcp 粘包
     1 import socket
     2 
     3 sockfd = socket.socket(socket.AF_INET,
     4                        socket.SOCK_STREAM)
     5 sockfd.bind(('0.0.0.0', 8888))
     6 
     7 sockfd.listen(3)
     8 
     9 while True:
    10   print("Waiting for connect ...")
    11   connfd, addr = sockfd.accept()
    12   print("Connect from", addr)
    13 
    14   n = 0
    15   while n < 10:
    16     n += 1
    17     data = connfd.recv(5)
    18     print(data)
    19 
    20   connfd.close()  # 断开连接
    21 
    22 # 关闭套接字
    23 sockfd.close()
    tcp粘包问题

    练习:将一个文件从客户端发送到服务端,要求文件类型随意.
    思路:读取文件--> send发送       recv接收--> write写入

     1 from socket import *
     2 import time
     3 #    读取文件--> send发送
     4 s = socket()
     5 s.connect(('127.0.0.1',8888))
     6 
     7 f = open('img.jpg','rb')
     8 
     9 # 读取内容,将其发送
    10 while True:
    11   data = f.read(1024)
    12   if not data:
    13     time.sleep(0.1)
    14     s.send(b'##')
    15     break
    16   s.send(data)
    17 
    18 time.sleep(0.1)
    19 s.send("发送完毕".encode())
    20 
    21 f.close()
    22 s.close()
    23 ---------------------------------------------
    24 from socket import *
    25 
    26 s = socket()
    27 s.bind(('0.0.0.0',8888))
    28 s.listen(3)
    29 
    30 c,addr = s.accept()
    31 print("Connect from",addr)
    32 
    33 # 以二进制写入
    34 f = open('mm.jpg','wb')
    35 
    36 #循环接收内容,写入文件
    37 while True:
    38 #    recv接收--> write写入
    39   data = c.recv(1024)
    40   if data == b'##':
    41     break
    42   f.write(data)
    43 
    44 data = c.recv(1024)
    45 print(data.decode())
    46 
    47 f.close()
    48 c.close()
    49 s.close()
    练习
  • 相关阅读:
    Python界面常用GUI包
    ATSC/DVB/ISDB三大标准比较
    【MPEG】DVB / ATSC / ISDB区别
    Python判断字符串是否为字母或者数字
    MApp_ZUI_CTL_MarqueeTextWinProc字串滚动
    PWM原理及其在电源中的应用
    按键板的原理与实现 扩展GPIO
    按键板的原理与实现----ADC
    使用with语句来写一个稍微复杂sql语句,附加和子查询的性能对比
    SQL Server备份还原数据库中的小把戏
  • 原文地址:https://www.cnblogs.com/maplethefox/p/10988950.html
Copyright © 2020-2023  润新知