1.创建server.py
# _*_ coding:utf-8 _*_
#服务端
import socket
import threading
#接收客户端发送过来的消息,conn是连接,nick是传过来的消息
def clientThreadIn(conn,nick):
global data
while True:
try:
#temp用来存客户端传过来的消息
temp=conn.recv(1024) #接收客户端发过来的消息
#若传过来为空,即没有消息
if not temp:
conn.close() #关闭连接
return #返回空
#否则唤醒进程
NotifyAll(temp)
print data
except:
NotifyAll(nick+'leaves the room!') #出现异常退出
print data
return
#服务端发送信息,发送到各个客户端
def clientThreadOut(conn,nick):
global data
while True:
if con.acquire(): #获取下面threading.active_count进程的锁
con.wait() #会阻塞,放弃对资源占有,等待通知(通知是NotifyAll函数),然后运行后面的代码
#如果data存在
if data:
try:
conn.send(data)
conn.release()
except:
conn.release()
return
# 唤醒进程
def NotifyAll(ss):
global data
if con.acquire(): #获取锁,只有我这个线程可以操作
data=ss
con.notifyAll() #单前线程放弃对资源占有,通知所有等待线程从wait方法执行
con.release()
con=threading.Condition() #条件
HOST=raw_input('input the server ip address:')
port=8889
data=''
#创建套接字,先创建服务端,再客户端连接服务端
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
print 'Socket created'
#把套接字绑定ip地址
s.bind((HOST,port))
s.listen(5) #监听客户端
print 'Socket now listening'
while True:
conn,addr=s.accept() #接收连接,conn是连接客户端的一些参数,addr是从客户端过来的ip和端口
#打印addr[0]是客户端传过来的ip,addr[1]是客户端传过来的端口号
print 'Connected with'+addr[0]+':'+str(addr[1])
nick=conn.recv(1024) #获取客户端过来的用户名
NotifyAll('welcome'+nick+'to the room!')
print data
# threading.active_count获取当前进程的线程数量,一个客户端创建2个线程,一个人创建2个线程,故/2
print str((threading.active_count()+1)/2)+'person(s)' #获取当前房间人数
conn.send(data) #将数据发送给聊天室的所有人,
#将数据发送给客户端
threading.Thread(target=clientThreadIn,args=(conn,nick)).start()
threading.Thread(target=clientThreadOut,args=(conn,nick)).start()
2.创建客户端client.py
# _*_ coding:utf-8 _*_
#socket 服务端和客户端 服务端监听 客户端请求 连接确认
import socket
import threading
nick=''
outstring=''
instring=''
#发送到服务端信息
def Dealout(sock):
global nick,outstring
while True:
outstring=raw_input() #输入
outstring=nick+':'+outstring
sock.send(outstring) #发送
#客户端接收的信息
def DealIn(sock):
global instring
while True:
try:
instring=sock.recv(1024) #接收1024字节
if not instring: #若接收的是空字节
break
if outstring !=instring: #若接收信息不等于发送信息
print instring
except:
break
nick=raw_input('input your nickname:')
ip=raw_input('input the server ip address;')
#创建套接字,Socket=Ip address+ TCP/UDP + port,套接字,是支持TCP/IP的网络通信的基本操作单元,
# 可以看做是不同主机之间的进程进行双向通信的端点
#AF_INET(又称 PF_INET)是 IPv4 网络协议的套接字类型,AF_INET6 则是 IPv6 的;而 AF_UNIX 则是 Unix 系统本地通信
#选择 AF_INET 的目的就是使用 IPv4 进行通信。因为 IPv4 使用 32 位地址,相比 IPv6 的 128 位来说,计算更快,便于用于局域网通信。
#而且 AF_INET 相比 AF_UNIX 更具通用性,因为 Windows 上有 AF_INET 而没有 AF_UNIX
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #参数:ipv4,流式
sock.connect((ip,8889)) #这里接收的是元组,发起请求
sock.send(nick) #让服务端接收到
#多线程 接受信息 发送信息
#创建接收信息
thin=threading.Thread(target=DealIn,args=(sock,)) #target接收的是函数,args接收的是元组,元组中只有一个值时,要加上逗号
thin.start()
#创建发送信息
thout=threading.Thread(target=Dealout,args=(sock,))
thout.start()
3.创建批处理文件
(1)cmd.bat文件中输入:cmd.exe 保存
(2)打开cmd.bat,输入server.py,运行server.py,输入ip:127.0.0.1 注意:若端口号已经用过,则要换其他端口号
(3)打开多个cmd.bat,输入client.py,运行client.py.输入:nickname名字,连接的服务器ip为127.0.0.1
(4)服务器只是接受信息,并把接受到的信息发给所有客户端,每个客户端接收到的信息都是以nickname区分开的