【python网络编程】利用select实现socket全双工异步通信

    在上一篇博文中,我们实现了tcp客户端与服务器的通信,但是功能十分局限,发送消息与接收消息不能同时进行。

    接下来我将通过select这个模块,来实现全双工通信(随时可以接收信息以及发送信息),当然,用多线程也可以完成,这是后话。

    那么,select为何物?

    select  -在单线程网络服务中器程序中,管理多个套接字连接

    select的原型为(rlist,wlist,xlist[,timeout]),其中rlist是等待读取的对象,wlist是等待写入的对象,xlist是等待异常的对象,最后一个是可选对象,指定等待的时间,单位是s. 

    select()方法的返回值是准备好的对象的三元组,若在timeout的时间内,没有对象准备好,那么返回值将是空的列表。

    它采用的是轮询的方式来实现异步通信的。

    在下面程序中,目前主要支持1对1通信,当双方任何一方发送字符串‘88’时,表示结束通信。

    下面我们来看看具体实现:

     首先是服务器。

#!/usr/bin/python

'test TCP server'

from socket import *
from time import ctime
import select
import sys

HOST = ''
PORT = 21567
BUFSIZ = 1024
ADDR = (HOST, PORT)

tcpSerSock = socket(AF_INET, SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)
input = [tcpSerSock, sys.stdin]     #input是一个列表,初始有欢迎套接字以及标准输入

while True:
	print 'waiting for connection...'
	tcpCliSock, addr = tcpSerSock.accept()
	print '...connected from:',addr
	input.append(tcpCliSock)    #将服务套接字加入到input列表中
	while True:
		readyInput,readyOutput,readyException = select.select(input,[],[])  #从input中选择,轮流处理client的请求连接(tcpSerSock),client发送来的消息(tcpCliSock),及服务器端的发送消息(stdin)
		for indata in readyInput:
			if indata==tcpCliSock:    #处理client发送来的消息
				data = tcpCliSock.recv(BUFSIZ)
				print data
				if data=='88':
					input.remove(tcpCliSock)
					break
			else:			  #处理服务器端的发送消息
				data = raw_input('>')
				if data=='88':
					tcpCliSock.send('%s' %(data))
					input.remove(tcpCliSock)
					break
				tcpCliSock.send('[%s] %s' %(ctime(), data))
		if data=='88':
			break
	tcpCliSock.close()
tcpSerSock.close()


    以下是客户端的代码,非常类似,只是与服务器相比不需要处理请求信息而已。

#!/usr/bin/python

'test tcp client'

from socket import *
from time import ctime
import select
import sys

HOST = 'localhost'
PORT = 21567
BUFSIZ = 1024
ADDR = (HOST, PORT)
tcpCliSock = socket(AF_INET, SOCK_STREAM)
tcpCliSock.connect(ADDR)
input = [tcpCliSock,sys.stdin]

while True:
	readyInput,readyOutput,readyException = select.select(input,[],[])
	for indata in readyInput:
		if indata==tcpCliSock:
			data = tcpCliSock.recv(BUFSIZ)
			print data
			if data=='88':
				break	
		else:
			data = raw_input('>')
			if data=='88':	
				tcpCliSock.send('%s' %(data))
				break
			tcpCliSock.send('[%s] %s' %(ctime(), data))
	if data=='88':	
		break
tcpCliSock.close()


    目前为止,已经实现了一对一全双工聊天通信啦。

    下面当然要思考下,如何实现多对多通信呢?

    我们知道,一个服务器可以为多个客户端服务,即,服务器与客户端本身有着一对多的关系,那么,我们是否可以利用服务器作为中间人,用来传达信息,从而实现多对多通信呢?

   举个例子,A想要和B通信,则A将信息发送给服务器,然后再通过服务器转发给B。按照这个思路去写,完成多对多通信应该是可以的,有兴趣的可以尝试一下。

你可能感兴趣的:(python,tcp,socket,网络编程,套接字)