无需多线程,实现全双工(异步)通信

实现两个用户全双工通信:
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/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值