Python builds TCP communication / TCP forwarding

Python builds TCP communication

TCP/IP protocol

TCP/IP (Transmission Control Protocol/Internet Protocol) refers to a protocol cluster that can realize information transmission between multiple different networks. TCP/IP protocol refers not only to TCP and IP Two agreements, but one by FTP,SMTP,TCP,UDP The protocol cluster composed of, IP and other protocols is called TCP/IP protocol because TCP protocol and IP protocol are the most representative among TCP/IP protocols.

TCP protocol processing of Python

To be honest, python does not have much advantage in this kind of low-level network protocol processing. Its processing speed is relatively slow compared with C/C + + or any other language, but the victory lies in the simple wwwww

Using Python to realize tcp communication is generally realized through Python's socket module.

socket is Python's own source library. You don't need to download it through pip. Just import it into the code.

socket module provided by Python, which provides standard BSD Sockets API

socket type

Let's take a look at the socket constructor first

socket.socket([family[, type[, proto]]])
class socket(_socket.socket):

    """A subclass of _socket.socket adding the makefile() method."""

    __slots__ = ["__weakref__", "_io_refs", "_closed"]

    def __init__(self, family=-1, type=-1, proto=-1, fileno=None):
        pass
    # Omitted below

family:

The meaning is address family, which determines the communication type of socket. The type and description are as follows

socket address family typeAddress family description
socket.AF_UNIXIt can only be used for inter process communication of a single Unix system
socket.AF_INETNetwork communication between servers
socket.AF_INET6IPv6

type:

The meaning is socket type. Different connections are built according to different values. The types and descriptions are as follows

socket typeType description
socket.SOCK_STREAMStreaming socket, which is used to handle TCP connections
socket.SOCK_DGAMDatagram socket, which is used to handle UDP connections
socket.SOCK_RAWThe original type of socket, ordinary socket can not handle ICMP, IGMP and other network messages, while SOCK_RAW is OK; Meanwhile, SCOK_RAW can also handle special IPv4 messages; Using the original socket, you can use IP_ The hdrincl socket option constructs the IP header by the user.
socket.SOCK_SEQPACKETReliable continuous packet service

protocol:

Generally, it is not filled in, and the default value is 0.

socket function

1) Unlike HTTP or UDP protocols, TCP has established a TCP connection when sending data, so there is no need to specify an address.
2) The server and client cannot directly send data types other than * * * string * * *.
3) The available functions are as follows

Server function

socket functionFunction description
bind(address)Bind the socket to the address in AF_ In INET address family mode, the address is represented in the form of tuple (host,port)
listen(backlog)Start listening for TCP incoming connections. bcaklog specifies the maximum number of connections that the operating system can suspend before rejecting the connection. This value is at least 1, which is valid in Win/MAC system. The default maximum value under Linux system.
accept()Accept TCP connection and return to conn (address). Conn is a new socket object that can be used to receive and send data. Address is the address of the connecting client.

Client function

socket functionFunction description
connect(address)Connect to the socket at address. Generally, the format of address is tuple (hostname,port). If there is a connection error, socket is returned Error error.
connect_ex(address)The function is the same as that of connect(address), but 0 is returned for success and errno is returned for failure.

General function

socket functionFunction description
recv(bufsize[,flag])Accept data from TCP sockets. Data is returned in byte form, and bufsize specifies the maximum amount of data to be received. flag provides additional information about the message, which can usually be ignored.
send(byte[,flag])Send TCP data. Send the data in byte to the connected socket. The return value is the number of bytes to send, which may be less than the byte size of string.
sendall(byte[,flag])Send TCP data completely. Send the data in byte to the connected socket, but try to send all the data before returning. None is returned successfully, and an exception is thrown if it fails.
recvfrom(bufsize[.flag])Accept data from UDP socket. Similar to recv(), but the return value is (data,address). Where data is the string containing the received data, and address is the socket address of the sending data.
sendto(string[,flag],address)Send UDP data. Send the data to the socket. Address is a tuple in the form of (ipaddr, port) and specifies the remote address. The return value is the number of bytes sent.
close()Close socket
getpeername()Returns the remote address of the connection socket. The return value is usually a tuple (ipaddr,port).
getsockname()Returns the socket's own address. Usually a tuple (ipaddr,port)
setsockopt(level,optname,value)Sets the value of the given socket option.
getsockopt(level,optname[.buflen])Returns the value of the socket option.
settimeout(timeout)Set the timeout of socket operation. Timeout is a floating-point number in seconds. A value of None indicates that there is no timeout. In general, timeout periods should be set when a socket is first created, as they may be used for connection operations (such as connect())
gettimeout()Returns the value of the current timeout period in seconds. If the timeout period is not set, it returns None.
fileno()Returns the file descriptor of the socket.
setblocking(flag)If the flag is 0, set the socket to non blocking mode, otherwise set the socket to blocking mode (default). In non blocking mode, if the call recv() does not find any data, or the call send() cannot send data immediately, it will cause socket Error exception.
makefile()Create a file associated with the socket

socket programming

thinking

There should be a socket on the server to listen to a port, accept the connection established from the client, receive the message sent from the client and send the message to the client.
There should be a socket on the server side, which uses a port to request the server side to build a TCP connection, send messages, and receive messages sent from the server side.

Pseudo code

Server:

1. Create a socket and bind it to the local IP and port

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('127.0.0.1', 8892))

2. Start listening port

s.listen(5)

3. Enter the loop and continuously accept the connection request of the client

s.accept()

4. Receive the data and send the return information to the client

s.recv(1024)
s.send()

5. Close the socket after the transmission or demand is completed

s.close()

client:

1. Create a socket and connect to the server

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect()

2. Send and receive data

data = 'data'
s.send(data)
s.recv()

3. Close the socket after the transmission or demand is completed

s.close()

Sketch Map

code

Server:

# server.py
import socket


class Server:
    def __init__(self, family, t, port):
        self.sock = socket.socket(family, t)
        self.sock.bind(('0.0.0.0', port))
        self.sock.listen(10)

    def accept(self):
        self.sock.accept()


if __name__ == '__main__':
    server = Server(socket.AF_INET, socket.SOCK_STREAM, 7792)
    client, client_addr = server.sock.accept()
    print('come from:' + str(client_addr) + 'Connection of')
    data = client.recv(1024)
    print('Received from:' + str(client_addr) + 'Message:')
    # The received data is byte and needs to be converted into string
    print(str(data, 'utf-8'))
    # Sending data needs to be converted into byte
    client.send(str('Hello,I have received the message!').encode())

client:

# client.py
import socket


class Client:
    def __init__(self, family, t, ip, port):
        self.sock = socket.socket(family, t)
        self.ip = ip
        self.port = port

    def connect(self):
        self.sock.connect((self.ip, self.port))

    def recv(self, size):
        return self.sock.recv(size)

    def send(self, byteData):
        self.sock.send(byteData)

    def close(self):
        self.sock.close()


if __name__ == '__main__':
    client = Client(socket.AF_INET, socket.SOCK_STREAM, '127.0.0.1', 7792)
    client.connect()
    client.send(str('Hello!').encode())
    data = client.recv(1024)
    client.close()
    print('Message from server:\n' + str(data, 'utf-8'))

Operation results

Start the server first and then the client
Server result:

Client results:

Using threads to operate socket s

# Realize tcp request forwarding
import sys, socket, time, threading, json

# Log lock makes log output thread safe
loglock = threading.Lock()

def log(msg, ip):
    loglock.acquire()
    try:
        print('[%s]: \n[IP:%s]\n%s\n' % (time.ctime(), ip, msg.strip()))
        sys.stdout.flush()
    finally:
        loglock.release()

# Transport class, with source as the source and target as the target
# Forwarding principle: the server establishes a connection with the client, and the server establishes a connection with the forwarding target
# The server gets two sock s and uses PipeThread to exchange messages
class PipeThread(threading.Thread):

    def __init__(self, source, target, addr):
        threading.Thread.__init__(self)
        self.source = source
        self.target = target
        self.addr = addr

    def run(self):
        while True:
            try:
                data = self.source.recv(1024)
                log('datas:', self.addr)
                print(data)
                if not data:
                    break
                self.target.send(data)
            except Exception as e:
                print(e)
                break
        log('PipeThread done', self.addr)


class Forwarding(threading.Thread):
    def __init__(self, port, targethost, targetport):
        threading.Thread.__init__(self)
        self.targethost = targethost
        self.targetport = targetport
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.bind(('0.0.0.0', port))
        self.sock.listen(10)

    def run(self):
        while True:
            client_fd, client_addr = self.sock.accept()
            target_fd = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            target_fd.connect((self.targethost, self.targetport))
            log('new connect', client_addr)
            PipeThread(target_fd, client_fd, '(' + self.targethost + ':' + str(self.targetport) + ")").start()
            PipeThread(client_fd, target_fd, client_addr).start()


# two direct pipe


if __name__ == '__main__':
    Forwarding(8928, '10.110.87.243', 8879).start()
    sys.exit(1)

Keywords: Python Operation & Maintenance network http TCPIP

Added by EPCtech on Wed, 26 Jan 2022 22:22:54 +0200