实现两个用户全双工通信:
1,第一个想法是,在服务器端设置一个字典,保存有用户的位置与名称,然后服务器端根据用户发过来的信息
来进行转发。但是后来发现实样不行。原因在于python中的socket作为server一旦与一个client连接之后进
入accept()函数后,在收到消息之前一直处于阻塞状态。通俗点说就是,服务器端不能主动发起通信。第一
方案放弃,不过主要思路应该是正确的,只是利用我现有的知识无法实现就是,QQ想必就是这样实现的吧,
否则,它怎么知道我在发什么内容呢,如果不知道,又谈何敏感字呢?
2,第二个想法是就更简单了,每个用户既有server的socket,又有作为client的socket.前提是必须要有一个要
输入与输出分开,再还没有接触GUI编程前,这个想法也放弃吧。
3,第三个想法,呵呵,没有第三个了,只好去找想关技术了,最张还是被我找到了,select.下面就来介绍下这
个select模块。下面是参考书上的简要介绍:
select -在单线程网络服务中器程序中,管理多个套接字连接
单线程管理多个连接,想想了知道,肯定是利用轮循机制,即重复查看是否有信息需要处理(client的请求连接,client发送来的消息,及服务器端的发送消息)。同样,在client端同样需要实现这样的一个轮循机制,只是比server端少了一个处理请求连接。废话少说,上代码:
server端:
import time
import select
import socket
import sys
host = ''
port = 50021
backlog = 5
size = 1024
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host,port))
server.listen(backlog)
input = [server,sys.stdin]
running = 1
print 'waiting connection...'
client, address = server.accept()
print "connecte to...",address
input.append(client)
while running:
print '>',
inputready,outputready,exceptready = select.select(input,[],[])
for s in inputready:
if s == sys.stdin:
# handle standard input
serMsg = raw_input()
if serMsg == '^c':
running = 0
client.send(serMsg)
client.close()
break
client.send("server at -%s-:\n%s"%(time.ctime(),serMsg))
else:
# handle all other sockets
data = s.recv(size)
if data:
print data
server.close()
print 'server is over'
client端:
import sys
import select
from socket import *
from time import ctime
HOST = 'localhost'
PORT = 50021
size = 1024
addr = (HOST,PORT)
client = socket(AF_INET,SOCK_STREAM)
client.connect(addr)
input = [sys.stdin,client]
running = 1
while running:
print '>',
readyInput,readyOupt,readyException = select.select(input,[],[])
for c in readyInput:
if c == client:
data = client.recv(size)
if data == '^c':
running = 0
print 'server exist'
c.close()
print 'client is over'
break
print data
else:
cliMsg = raw_input()
client.send("client at -%s-:\n%s"%(ctime(),cliMsg))
下面对关键代码进行解析:
print 'waiting connection...'
client, address = server.accept()
print "connecte to...",address
input.append(client)
server端在有client端connect它时,接收其连接要求(具体内容详见tcp建立连接的过程),即accept()函数,将这个连接交给一个新的socket,名称为client。将这个socket加入到等待输入的列表中,以便select检测其发送来的消息
inputready,outputready,exceptready = select.select(input,[],[])
这个才是用单纯程来实现全双工的异步通信的关键所在,每次循环都会轮循输入(其中这儿有两种可能的输入,一个是来自stdin,默认是键盘;另一个来自client链接发送来的消息,即client这个socket)
for s in inputready:
...
下面的循环就是用来检测各个可能的输入,但并不会阻塞在各个输入接口(如以前会阻塞在recv这个函数处)。
同样,client端也是要用select来检测键盘与server端的输入。
这个程序只能实现两个用户之间的通信,改进的地方是在server端,能够接收多个client连接,将它们保存起来,为以后接收到消息后进行有针对性的回复。这样可以实现一对多的通信,如何实现多对多的通信呢?
1,第一个想法是,在服务器端设置一个字典,保存有用户的位置与名称,然后服务器端根据用户发过来的信息
来进行转发。但是后来发现实样不行。原因在于python中的socket作为server一旦与一个client连接之后进
入accept()函数后,在收到消息之前一直处于阻塞状态。通俗点说就是,服务器端不能主动发起通信。第一
方案放弃,不过主要思路应该是正确的,只是利用我现有的知识无法实现就是,QQ想必就是这样实现的吧,
否则,它怎么知道我在发什么内容呢,如果不知道,又谈何敏感字呢?
2,第二个想法是就更简单了,每个用户既有server的socket,又有作为client的socket.前提是必须要有一个要
输入与输出分开,再还没有接触GUI编程前,这个想法也放弃吧。
3,第三个想法,呵呵,没有第三个了,只好去找想关技术了,最张还是被我找到了,select.下面就来介绍下这
个select模块。下面是参考书上的简要介绍:
select -在单线程网络服务中器程序中,管理多个套接字连接
单线程管理多个连接,想想了知道,肯定是利用轮循机制,即重复查看是否有信息需要处理(client的请求连接,client发送来的消息,及服务器端的发送消息)。同样,在client端同样需要实现这样的一个轮循机制,只是比server端少了一个处理请求连接。废话少说,上代码:
server端:
import time
import select
import socket
import sys
host = ''
port = 50021
backlog = 5
size = 1024
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host,port))
server.listen(backlog)
input = [server,sys.stdin]
running = 1
print 'waiting connection...'
client, address = server.accept()
print "connecte to...",address
input.append(client)
while running:
print '>',
inputready,outputready,exceptready = select.select(input,[],[])
for s in inputready:
if s == sys.stdin:
# handle standard input
serMsg = raw_input()
if serMsg == '^c':
running = 0
client.send(serMsg)
client.close()
break
client.send("server at -%s-:\n%s"%(time.ctime(),serMsg))
else:
# handle all other sockets
data = s.recv(size)
if data:
print data
server.close()
print 'server is over'
client端:
import sys
import select
from socket import *
from time import ctime
HOST = 'localhost'
PORT = 50021
size = 1024
addr = (HOST,PORT)
client = socket(AF_INET,SOCK_STREAM)
client.connect(addr)
input = [sys.stdin,client]
running = 1
while running:
print '>',
readyInput,readyOupt,readyException = select.select(input,[],[])
for c in readyInput:
if c == client:
data = client.recv(size)
if data == '^c':
running = 0
print 'server exist'
c.close()
print 'client is over'
break
print data
else:
cliMsg = raw_input()
client.send("client at -%s-:\n%s"%(ctime(),cliMsg))
下面对关键代码进行解析:
print 'waiting connection...'
client, address = server.accept()
print "connecte to...",address
input.append(client)
server端在有client端connect它时,接收其连接要求(具体内容详见tcp建立连接的过程),即accept()函数,将这个连接交给一个新的socket,名称为client。将这个socket加入到等待输入的列表中,以便select检测其发送来的消息
inputready,outputready,exceptready = select.select(input,[],[])
这个才是用单纯程来实现全双工的异步通信的关键所在,每次循环都会轮循输入(其中这儿有两种可能的输入,一个是来自stdin,默认是键盘;另一个来自client链接发送来的消息,即client这个socket)
for s in inputready:
...
下面的循环就是用来检测各个可能的输入,但并不会阻塞在各个输入接口(如以前会阻塞在recv这个函数处)。
同样,client端也是要用select来检测键盘与server端的输入。
这个程序只能实现两个用户之间的通信,改进的地方是在server端,能够接收多个client连接,将它们保存起来,为以后接收到消息后进行有针对性的回复。这样可以实现一对多的通信,如何实现多对多的通信呢?
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/24927532/viewspace-702525/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/24927532/viewspace-702525/