http://www.oschina.net/code/snippet_1992504_44586
这位兄台写了个半双工的, 花半小时写了个全双工的
测试了一下,应该实现了基本功能, 后续会添加更多功能,包括取昵称,更改昵称,私聊等
1.[代码]python chat_server
__author__ = '’
import socket
import select
HOST = ""
PORT = 9008
BACKLOG = 100
BUFF = 1024
ADDR = (HOST, PORT)
CONNECT_MAP = {}
def broadcast_msg(_srv_sock, my_sock, msg):
for _file_no, _sock in CONNECT_MAP.iteritems():
if _sock != _srv_sock and _sock != my_sock:
try:
_sock.send(msg)
except socket.error:
pass
def chat_server():
srv_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
srv_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
srv_sock.bind(ADDR)
srv_sock.listen(BACKLOG)
_epoll = select.epoll()
_epoll.register(srv_sock.fileno(), select.EPOLLIN)
print "Start chat server on port %d" % PORT
while True:
events = _epoll.poll(timeout=0.5)
for _file_no, event in events:
if _file_no == srv_sock.fileno():
_cli_sock, _addr = srv_sock.accept()
_cli_sock.setblocking(0)
print "Client (%s, %s) connected" % _addr
broadcast_msg(srv_sock, _cli_sock, "[%s:%s] entered root\n\r" % _addr)
_epoll.register(_cli_sock.fileno(), select.EPOLLIN)
CONNECT_MAP[_cli_sock.fileno()] = _cli_sock
elif event & select.EPOLLIN:
try:
_sock = CONNECT_MAP[_file_no]
_data = _sock.recv(BUFF)
if _data:
_msg = "" + _data + '\n\r'
broadcast_msg(srv_sock, _sock, _msg)
except:
CONNECT_MAP[_file_no].close()
CONNECT_MAP.pop(_file_no)
_epoll.unregister(_file_no)
elif event & select.EPOLLHUP:
CONNECT_MAP[_file_no].close()
CONNECT_MAP.pop(_file_no)
_epoll.unregister(_file_no)
if __name__ == "__main__":
chat_server()
2.[代码]python chat_client
__author__ = ''
import select
import string
import sys
import socket
# default server address
HOST = "localhost"
PORT = 9008
BUFF = 4096
if len(sys.argv) == 3:
HOST = sys.argv[1]
PORT = int(sys.argv[2])
def chat_client():
cli_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
cli_sock.connect((HOST, PORT))
except:
print "Connect to chat server failed"
sys.exit(-1)
print "succ connected to chat server, now please enter your words"
sys.stdout.write("I>")
sys.stdout.flush()
_epoll = select.epoll()
_epoll.register(sys.stdin.fileno(), select.EPOLLIN)
_epoll.register(cli_sock.fileno(), select.EPOLLIN | select.EPOLLOUT | select.EPOLLERR)
while True:
events = _epoll.poll(0.5)
for _file_no, event in events:
if _file_no == cli_sock.fileno() and event & select.EPOLLIN:
_data = cli_sock.recv(BUFF)
if not _data:
print "Disconnected from chat server"
sys.exit(-1)
else:
sys.stdout.write(_data)
sys.stdout.write("I>")
sys.stdout.flush()
elif event & select.EPOLLIN:
_msg = sys.stdin.readline()
cli_sock.send(_msg)
sys.stdout.write("I>")
sys.stdout.flush()
if __name__ == "__main__":
chat_client()