3

Python Network Programming

 2 years ago
source link: https://daya-jin.github.io//2019/11/22/PythonNetworkProgramming/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Basic

一个简单的TCP回显服务器与客户端程序。

 server.py

import socket

HOST = socket.gethostname()
PORT = 50007

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen(1)    # 积压连接数
    conn, addr = s.accept()    # 返回新sock对象与连接地址
    with conn:
        print('Connected by', addr)
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)    # 发送所有数据

 client.py

import socket

HOST = '192.168.10.128'  # The remote host
PORT = 50007  # The same port as used by the server
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect((HOST, PORT))
    s.sendall(b'Hello, world')    # 发送所有数据(字节流)
    data = s.recv(1024)    # 字节流
    print(type(data))
print('Received', repr(data))    # 字节流转字串

因为TCP是面向连接的协议,数据流是以packet的形式发送与接收的,如果发送消息过长会被分成多个包,同样接收方也会分多次接收。问题的根源在于,接收方不知道发送方要发送多长的数据,若发送方连续连续发送两条数据,接收方不知道数据之间的分割,因此将两条本应分开数据(的某部分)一起接收了,于是产生了黏包现象。UDP没有黏包问题。

黏包问题的解决方式也很简单,既然问题的根源在于接收方不知道发送数据的长度,那么在发送正式数据前发送方通知接收方的数据长度即可。

Struct

Python的struct模块是一个字节流解释器跟翻译器,一个最简单的示例,现有三个数1、2、3,如果要将其分别按不同的类型转成(翻译)字节流,可以使用下述代码:

import struct

print(struct.pack('ihb', 1, 2, 3))    # b'\x01\x00\x00\x00\x02\x00\x03'
print(struct.pack('!ihb', 1, 2, 3))    # b'\x00\x00\x00\x01\x00\x02\x03'

这里解释一下程序与输出。pack的第一个参数是格式字串,其后跟的全是需要转换的数据,格式参数必须跟数据一一对应。上述程序中的!表示网络字节序,i表示int(4Byte),h表示short(2Byte),b表示signed char(1Byte)。根据ihb的解释格式,1、2、3会被分别转换成:0x000000010x00020x03,然后按照不同的字节序会得到不同的字节流。

又比如,在ping程序的ICMP报文中,前88个字节即为ICMP的头部,如下图所示,ICMP的头部字节码为:\x08\x00\x4c\x60\x00\x01\x00\xfb

这里对ICMP的首部进行解码,由人工计算易得首部各字段的值应该为(8, 0, 19552, 1, 251),由struct模块解码得到的值与之一致:

import struct

data = b'\x08\x00\x4c\x60\x00\x01\x00\xfb'
print(struct.unpack('!BBHHH', data))    # (8, 0, 19552, 1, 251)

Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK