current position:Home>TCP / UDP communication based on Python socket

TCP / UDP communication based on Python socket

2022-02-01 14:08:39 Cheng Xuyuan Xiaozhuang

This article is participating in “ Network protocol must know and will ” Solicitation activities

If two applications need to communicate, the most basic premise is to uniquely identify a process , We know IP Layer of ip The address can uniquely identify the host , and TCP Layer protocol and port number can uniquely identify a process of the host , So we can use ip Address + agreement + The port number uniquely identifies a process in the network . After being able to uniquely identify the processes in the network , They can use socket We're communicating , This article will socket To introduce .

What is? socket

What is? socket Well ? We often put socket Socket ,socket It's an abstraction layer between the application layer and the transport layer , It is the TCP/IP The complex operation of layer is abstracted into several simple interfaces, and layer calls are used to realize the communication of processes in the network .

The purpose of learning network programming is to develop software based on Internet communication , Whether it's BS Architecture is still CS Architecturally . Our development of Internet communication software is in TCP/IP Application layer in five layer protocol , When it comes to data transmission through the Internet , You need to use it socket Abstraction layer . This socket Abstraction layer does not belong to TCP/IP Five floors , It's an abstract , Help us encapsulate other layers below the transport layer . It's complicated TCP/IP The protocol family is hidden in Socket The back of the interface , For users , A simple set of interfaces is all , Give Way Socket To organize data , To comply with the specified protocol . At development time , Just follow socket Write code according to the rules of , The written program naturally follows TCP/UDP agreement .

Socket development history and classification

Sockets originate 20 century 70 University of California, Berkeley version Unix, That's what people say BSD Unix. therefore , Sometimes people call sockets “ Berkeley socket ” or “BSD Socket ”. In limine , Sockets are designed to work with Communication between multiple applications on a host . This is also called interprocess communication , or IPC. There are two types of sockets ( Or there are two races ), They are file based and network-based .

A family of sockets based on file types

The name of the socket family :AF_UNIX, stay unix All documents in , File-based sockets call on the underlying file system to fetch data , Two socket processes run on the same machine , Communication can be done indirectly by accessing the same file system .

Socket family based on network type

The name of the socket family :AF_INET , also AF_INET6 Be used for ipv6, There are other address families , however , They are either used for a particular platform , Or it has been abandoned , Or it's rarely used , Or not at all , All address families ,AF_INET It's the most widely used one ,python Support many address families , But because we only care about network programming , So most of the time we just use AF_INET .

socket modular

socket It can realize the communication between the processes in the two networks , We can compare it with examples in daily life socket workflow , For example, you have to call a friend , Dial first , A friend picks up the phone when he hears it , That's when you connect with your friends , And you can talk . When the communication is over , Hang up and end the conversation . Scenes in life explain socket How it works .

Server side :

​ 1 initialization socket object

​ 2 socket Object and server IP And port binding (bind)

​ 3 Listen to the port (listen)

client :

​ 1 initialization socket object

​ 2 Connect to server (connect)

​ 3 If the connection is successful , The connection between the client and the server is established

After successful connection :

​ 1 Client sends data request

​ 2 The server receives the request and processes the request

​ 3 Send the response data to the client , Client reads data

​ 4 Close the connection , An interaction ends

python Medium socket The module is encapsulated socket Abstraction layer , It also provides some simple interfaces to help us realize the above process . The following code describes socket Basic use of modules :

Add :python How to view the source code : Hold down ctrl, Hover the mouse over the object that needs to view the source code , Click on , You can see the source code .

# socket_family  It can be  AF_UNIX  or  AF_INET.socket_type  It can be  SOCK_STREAM  or  SOCK_DGRAM.socket_family The default is -1, Express AF_INET,socket_type The default is -1, Express SOCK_STREAM. You can view it through the source code 
socket.socket(socket_family, socket_type, protocal=0)

#  obtain tcp/ip Socket 
tcp_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_sock = socket.socket()  #  The default is -1, Don't write 

#  obtain udp/ip Socket 
udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
 Copy code 

socket The module provides different methods for client program and server program to send and receive data , Some common methods are also provided . got it socket Usage of modules , So we can socket The module is based on TCP/UDP Protocol to develop small programs on the client and server . Let's introduce in turn :

First of all socket The module is the server (sever) Methods provided :

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  #  obtain socket object 
s.bind()   #  Bind host 、 Port number to socket 
s.listen()  #  Start TCP monitor 
s.accept()  #  Passive acceptance TCP Customer connection ,( Blocking type ) Waiting for the connection 
 Copy code 

The following term socket The module is the client (client) Methods provided :

import socket

s = socket.socket()  # socket object 
s.connect()  #  Actively initialize the connection TCP The server 
s.connect_ex()  # connect() Extended version of function , Error code returned when error , Instead of throwing an exception 
 Copy code 

Finally, some socket Some public methods for clients and servers :

s.recv()   #  receive TCP data 
s.send()   #  send out TCP data (send When the amount of data to be sent is greater than the remaining space of the end cache , Data loss , It won't end )
s.sendall()   #  Send complete TCP data ( The essence is circular calling send,sendall When the amount of data to be sent is greater than the remaining space of the end cache , Data is not lost , Cycle call send Until it's done )
s.recvfrom()   #  receive UDP data 
s.sendto()   #  send out UDP data 
s.getpeername()   #  The address of the remote connection to the current socket 
s.getsockname()   #  The address of the current socket 
s.getsockopt()   #  Returns the parameters of the specified socket 
s.setsockopt()   #  Set the parameters of the specified socket 
s.close()   #  Close socket connection 
 Copy code 

be based on TCP Socket

tcp The protocol is based on two-way connection , Therefore, the server must be started first , Then start the client to connect to the server .

Start with the server : Initialize the server first Socket, And then bind to the port (bind), Listen to the port (listen), call accept Blocking , Wait for the client to connect .

At this time, if there is a client initializing a Socket, And then connect to the server (connect), If the connection is successful , At this time, the connection between the client and the server is established .

Client sends data request , The server receives the request and processes it , Then send the response data to the client , Client reads data , Finally, close the connection , An interaction ends .

The above is based on TCP Simple flow of communication , Compare... According to the principle of making a phone call , The specific code is as follows :

Simple version TCP signal communication

Server files :

# sever.py  Server files 
#  Take mobile phone answering and making calls as an example 
import socket

# 1  Buy a cell phone --- Get the object that the server sends and receives data 
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

# 2  Cell phone card --- Bind to the server IP+ port 
phone.bind(('127.0.0.1',6666))

# 3  Turn it on --- The server is listening 
phone.listen(3)  #  The semi connection pool can only store three connection requests to be confirmed 

# 4  Waiting for a call --- The server establishes a connection with the client , After establishing the connection, you can get TCP Connected channel information , And the client IP And interface 
conn,client_addr = phone.accept()
print(conn)
print(' client IP And interface ',client_addr)

# 5  Connect the phone , They chatted happily --- Sending and receiving data 
data = conn.recv(1024)  #  The maximum amount of data received is 1024bytes
print(' Client message ', data.decode('utf-8'))
conn.send(data.upper())

# 6  Hang up --- Disconnect from the client 
conn.close()

# 7  Mobile phone shutdown --- Server shutdown 
phone.close()
 Copy code 

Client files

# client.py
import socket

phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

phone.connect(('127.0.0.1',6666))

phone.send('show  Information '.encode('utf-8'))

data = phone.recv(1024)

print(' Server side ',data.decode('utf-8'))

phone.close()
 Copy code 

TCP Circular communication

The above simple version of the communication code , There is a question , It took a lot of effort to connect successfully , As a result, the connection was disconnected by sending a message , It's like making a phone call , Say one word at a time , Hang up , If there's more to say , I need to call again ....

In order to solve the above problems , We can use loops to constantly receive or send data - Circular communication

Server files :

# sever.py
import socket

# 1  Buy a cell phone --- Get the object of the server 
phone = socket.socket()

# 2  Cell phone card --- Determine the of the server IP And port 
phone.bind(('127.0.0.1',7890))

# 3  Turn on the phone --- The server enters the listening state 
phone.listen(3)

# 4  Waiting to answer the phone , obtain TCP Channel and client IP And port 

conn,client_addr = phone.accept()

# 5  Call --- Sending and receiving data 
while True:
    #  exception handling : When preventing the client from shutting down suddenly, the server crashes 
    try:
        data = conn.recv(1024)
        if not data:break
        print(' client ',data.decode('utf-8'))

        conn.send(data.upper())
    except Exception:
        break

# 6  Hang up --- The server is disconnected from the client channel 
conn.close()

# 7  To turn it off --- Server shutdown 
phone.close()
 Copy code 

Client files :

# client.py
import socket

phone = socket.socket()
phone.connect(('127.0.0.1', 7890))
while True:
    info = input('>>').strip()
    #  When the length of the transmitted data is 0 when , Both the server and the client will enter the blocking stage waiting to receive data , So make a judgment , Judge that the information entered by the user is strip After processing , Is the length 0
    if len(info) == 0:continue
    if info == 'q': break
    phone.send(info.encode('utf-8'))
    data = phone.recv(1024)
    print(' Server side ', data.decode('utf-8'))

phone.close()
 Copy code 

The server is not closed TCP signal communication

There are also problems with the above code scheme , As a server, it should meet two conditions , One is to provide services for clients all the time , The second is to provide services concurrently , After the client is disconnected from the above circular communication , The server also stops running , You can no longer provide services to other clients . Therefore, we can keep the server in the state of not closing . The following is the optimized server code :

# sever.py
import socket

phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

phone.bind(('127.0.0.1',65447))

phone.listen(5)
while True:
    conn, client_addr = phone.accept()
    while True:
        try:
            data = conn.recv(1024)
            if not data:break
            print(' client ',data.decode('utf-8'))
            conn.send(data.upper())
        except Exception:
            break

    conn.close()  #  This is just to disconnect the client and server 
 Copy code 

Of course , The above code also needs to be optimized , That is, the server can only serve one client at the same time , If you want the server to serve multiple servers , We need to use the knowledge we will learn later - Concurrent programming . I won't give you too much introduction here .

In the use of TCP When communication , If the message sent by the client is empty , There will also be problems . If the message sent by the client is empty , In fact, this message will not be sent , It's just that the application sends this message to the operating system , After the operating system receives , Found empty , It won't go out . Therefore, the client sends an empty message and enters recv Equal state , At this time, the server does not receive any message at all and will not reply , So I fell into an awkward state of waiting on both sides . The solution is to judge whether the message sent by the client is empty , Skip directly to the next loop , Don't send this empty message to the operating system .

be based on UDP Socket

udp It's unlinked , No error will be reported at either end of the startup first . therefore , It's better than based on tcp The socket is much simpler to use .

UDP Protocol is datagram protocol , I also bring my own newspaper head when I'm empty , So the client input is empty , The server can also receive .

be based on udp The socket is not connected , Both client and server can start socket communication first , You can also end the communication in advance , That is, the departure of the client will not affect the normal operation of the server .

Server code

# server.py
import socket

ip_port = ('127.0.0.1', 8080)
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server.bind(ip_port)
print(' The server starts listening ......')

while True:
    get_msg, client_addr = server.recvfrom(1024)
    print('from client:', get_msg)
    server.sendto(get_msg.upper(), client_addr)

# server.close()
 Copy code 

Client code

import socket

ip_port = ('127.0.0.1', 8080)
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

while 1:
    msg = input('>>>:').strip()
    if msg == 'q':
        break
    if not msg:		#  Actually ,udp Socket , Support the client to send empty , The server can also receive empty 
        continue
    client.sendto(msg.encode('utf-8'), ip_port)
    get_msg, server_addr = client.recvfrom(1024)
    print(get_msg.decode('utf-8'))                     #  Close the client socket 
 Copy code 

Conclusion

The article begins with the official account of WeChat Cheng Xuyuan Village , Synchronize on Nuggets You know .

It's not easy to code words , Reprint please explain the source , Let's go after passing by with our lovely little fingers (╹▽╹)

copyright notice
author[Cheng Xuyuan Xiaozhuang],Please bring the original link to reprint, thank you.
https://en.pythonmana.com/2022/02/202202011408342196.html

Random recommended