python socket 通信与多线程
在之前我们已经介绍过了如何在golang中利用socket进行通信,在本文我们将介绍如何在python中编写socket函数进行通信。
在python中的socket通信与c中socket通信书写比较相似,以下为一个服务器端示例代码
import socket
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server_addr=('localhost',8888)
sock.bind(server_addr)
sock.listen(1)
conn,addr=sock.accept()
conn.send("hello".encode())
buff=conn.recv()
首先导入socket库,创建一个socket,指定协议族为AF_INET,该协议族表示因特网协议族,与AF_INET_IPV4等效,从名字上来看,我们使用该协议族的时候最好指定addr为ipv4地址,其他的协议族比如AF_INET_IPV6等等本文不再过多介绍,第二个参数指定socket type,有SOCK_STREAM, SOCK_DGRAM, SOCK_RAW三个,分别对应TCP,UDP,和其他协议(icmp等),一般来说我们通常使用tcp,设置为示例代码即可。接下来声明服务器端的地址,包括ip和端口号,因为tcp是唯一四元组区分的,需要注意的是应设置为(ip,port)的元组,ip为str,port为数字(应该是uint16,毕竟只占了16位),之后将我们设置好的socket和地址绑定(bind)起来,就可以监听端口了,listen()输入参数1表示最大连接队列的长度位1,也可以设置为其他数字处理多个连接。之后运行accept并阻塞直到有客户端连接,并进行收发。如果不希望在收发时被阻塞还可以利用threading库进行多线程操作
thread=threading.Thread(target=handle_conn(conn))
thread.start()
关于多线程此处多讲两句。python中有两个库,一个是subprocess一个是threading,subprocess是开一个新的进程,而threading是开一个新的线程,所以我们在python中设置的锁是无法阻塞subprocess的(虽然没有试过,但是理论上是这样的),但是可以阻塞threading创建的线程。我主要利用subprocess调用命令行执行其他进程,一般会是非阻塞调用,即利用popen,而不是run,subprocess还可以利用communicate等待进程结束已经poll判断是否结束。
然而在编程中虽然我们不能避免多线程多进程,我们在编写时需要格外小心,因为可能有些线程不会让cpu有空闲时间去执行其他线程,这会导致宏观上并没有多线程并行执行。