Socket communication and threads in Python

Want to write a software that can communicate between two different hosts? ? Want to imitate a software similar to the app store? ? ?

If you plan to develop network-related programs, such as chat software, then you absolutely cannot bypass network programming, and socket communication is a focus of network programming.

1. Definition of Socket

Two programs on the network exchange data through a two-way communication connection, and one end of this connection is called a socket. (Quoted from Baidu Encyclopedia) Emmmm... For students who want to understand the theoretical part, I suggest you to check the relevant content in other articles. Let's focus on the practical aspects.

2. A Simple Socket Communication Example

# -*-coding:utf-8 -*-
#   Server端
#   Server.py
import socket

HOST = '127.0.0.1'
PORT = 33333
ADDR = (HOST,PORT)
#  AF_INET 表示连接使用ipv4地址族  SOCK_STREAM表示用流式套接字
tcpSerSock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
tcpSerSock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# 将套接字绑定该地址
tcpSerSock.bind(ADDR)
# 参数1表示阻塞模式  0表示非阻塞模式  默认为阻塞模式
tcpSerSock.setblocking(1)
# 开始监听TCP传入连接。参数指定在拒绝连接之前,操作系统可以挂起的最大连接数量。
tcpSerSock.listen(5)

print "Waiting connect..."
# tcpCliSock 是该链接的套接字,addr表示对方的地址
tcpCliSock, addr = tcpSerSock.accept()
# 设置超时时间
tcpCliSock.settimeout(20.0)
print '...connected from', addr
# recv(param)用于接收对方发送的数据 param为缓冲区大小
data = tcpCliSock.recv(1024)
print data
tcpCliSock.sendall("here is server")
# 关闭套接字
tcpCliSock.close()

# -*- coding: utf-8 -*-
# client端
#  Client.py
import socket

address = ('127.0.0.1', 33333)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
s.connect(address)

s.sendall("here is client")
data = s.recv(1024)
print data
s.close()

operation result

server-side results

Client run results

The listen(x) method is used to listen for incoming TCP connections. The parameter specifies the maximum number of connections the operating system can suspend before rejecting the connection. Assuming that a host connects to the server, the server will establish a connection with a for socket communication. If host b also connects to the server before a disconnects from the server, the server will suspend the connection to b, and the server will not connect to b until a disconnects from the server. The parameter x of the listen method is the maximum number of connections that the server can suspend.

Friends who want to know more about the methods of the socket module, the detailed usage methods and parameters, can read this article

However, in practical applications, the server often needs to connect with multiple clients at the same time, so what should we do? ? ? ? The solution can be to enable multi-threading or multi-process. Multiprocessing is more expensive than multithreading, but for today's server (Linux-based) configurations, these costs are largely negligible.

Let's talk about multithreaded servers first today.

3.1 Multithreading

Multithreading refers to the technology that realizes the concurrent execution of multiple threads from software or hardware. Computers with multi-threading capabilities have hardware support to be able to execute more than one thread at a time, thereby increasing overall processing performance.

Understanding Multithreading with a Simple Example

# -*- coding:utf-8 -*-
# simpleThread_1.py
import threading
import time

def process():
    n = 0
    while(n<5):
        print str(n)+": the threading %s is running"%threading.current_thread().name
        n = n + 1
        time.sleep(1)
# 创建新线程  target为线程要执行的方法  name为进程的名字,name参数可以省略,其实名字基本无多大用处
t1 = threading.Thread(target=process,name="One")
t2 = threading.Thread(target=process,name="Two")
t1.start()
t2.start()

then threads t1 and t2 will be able to run at the same time

SimpleThread_1.py running results

If you add multiple: t1.join() between t1.start() and t2.start(), then thread t2 will not start running until t1 finishes running

3.2 Multithreaded server

#-*- coding:utf-8 -*-
#   多线程服务器   
#   threads_Server.py
import socket
import select
import threading
import time


def process(tcpCliSock,addr):
    print "connect from "+str(addr)
    pattern_data = tcpCliSock.recv(1024)
    print data
    tcpCliSock.sendall("here is server")
    


def run():
    server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server.bind(("127.0.0.1",33333))
    server.listen(5)
    while True:
        r,w,e = select.select([server,],[],[],1)
        # enumerate()分别列举出list r中的序号和内容
        for i,server in enumerate(r):
            conn,addr = server.accept()
            t = threading.Thread(target=process,args=(conn,addr))
            t.start()


if __name__=="__main__":
    run()

Of course, in fact, the more common application scenario of multi-threaded servers lies in long connections.

Well then, we have another problem. The client may suddenly disconnect from the connection, but the server does not find it, how sad the server must be, and it doesn't know [escape] after being cheated on. The multi-threaded server faces the connection of so many clients, so how does it know whether the client is still connected to the server? So we launched another artifact: the heartbeat packet mechanism

The heartbeat packet can periodically send a data packet to the other party, and the TCP connection can be judged by the sending situation.

There are many design methods for the heartbeat packet mechanism, such as:

  • The client sends heartbeat packets to the server regularly, and the server sends a packet to the client after receiving the heartbeat packet, so that both parties can know whether the other party is online.
  • The server periodically sends a heartbeat packet to the client. If the sending fails, it means that the client has been disconnected. Otherwise, it means that the client is still connected. This belongs to the unilateral monitoring of the server.

There are more than two design schemes above, and the specific situation is analyzed in detail! ! ! Remember remember! !

Then let's take a look at what a multi-threaded server with a heartbeat package looks like~

#-*- coding:utf-8 -*-
#   多线程服务器(心跳包版)   
#   hreatBeat_Server.py
import socket
import select
import threading
import time

# 心跳包线程  
def hreatBeat(conn):
    sum = 0   # 无回应次数
    while True:
        time.sleep(10)
        if sum<3:
            try:
                conn.sendall("hreatBeat")
                sum=0
            except socket.error:
                sum = sum + 1
                continue
        else:
            conn.close()
            break

def process(tcpCliSock,addr):
    print "connect from "+str(addr)
    pattern_data = tcpCliSock.recv(1024)
    print data
    tcpCliSock.sendall("here is server")
     #  创建心跳包线程
     #  须记住,创建新线程时 args参数如果只有一个的话一定要加个逗号!!
    thr = threading.Thread(target=hreatBeat, args=(tcpCliSock,))
        thr.start()
        #  thr.is_alive() 用于监测进程thr是否还存在(即client是否还在连接中)
        while thr.is_alive():
            print "do everything you like here"
    


def run():
    server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server.bind(("127.0.0.1",33333))
    server.listen(5)
    while True:
        r,w,e = select.select([server,],[],[],1)
        # enumerate()分别列举出list r中的序号和内容
        for i,server in enumerate(r):
            conn,addr = server.accept()
            t = threading.Thread(target=process,args=(conn,addr))
            t.start()


if __name__=="__main__":
    run()

4. Summary

Getting started with Socket communication is easy, but going deep is not easy. If you want to improve, learn more and practice more! Believe that the above knowledge is enough for you to build a prototype of a successful server. As a programmer, requirements are the first, and everything must be analyzed in combination with specific requirements.

Friends who are learning programming and Python, it is difficult to learn by one person, and bloggers are also here. Here, a new deduction group has been created: 1020465983, which has prepared learning resources and fun projects for everyone. Welcome everyone to join and communicate.

Guess you like

Origin blog.csdn.net/weixin_56659172/article/details/124119776