hello 今天记录下自已第一次用python写网络编程写了一个类似QQ群的功能。
对于像OSI七层模型,TCP/IP协议,和一些网络协议例如:http FTP POP3 大家想学习的可以百度下或者看计算机网络这本书讲的挺好的,我就不废话了
python socket模块
python socket模块和C# C/C++使用socket差不多
简单介绍下socket的过程
- 使用socket模块的socket函数创建一个socket对象。然后通过对象调用其他函数来设置一个socket服务。通过bind(hostname,port)来指定服务的port 然后调用socket对象的accept函数 来等待客户端的连接。
服务端的代码如下 本人亲测有效
import socket,select
class ChatServer():
“”“聊天服务器系统
用于实现服务器的功能
“””
def __init__(self,host,port,numOfClients):
#初始化服务器
self.HOST = host
self.PORT = port
self.server_socket = socket.socket()
self.server_socket.bind((self.HOST,self.PORT))
self.server_socket.listen(numOfClients)
self.socket_list = [] #存放连接的客户
self.client_names = {} #存放连接到服务器的客户端名称
self.socket_list.append(self.server_socket)
print('聊天室已打开...')
def Connect(self):
client_conn,client_addr = self.server_socket.accept()
try:
welcome_msg = '欢迎来到聊天室,请输入昵称:'
client_conn.send(welcome_msg.encode('utf-8'))
#接收发来的名称
client_name = client_comm.rev(4096).decode('utf-8')
self.socket_list.append(client_conn)
self.client_names[client_conn] = client_name
msg = '现在有' + str(len(self.client_names)) +'名用户在聊天室 : ['+','.join(list(self.client_names.values())) + ']'
client_conn.send(msg.encode('utf-8'))
#向所有的用户发送新成员
for sock in self.client_names.keys():
if (not sock == client_conn):
msg = self.client_names[client_conn]+'加入聊天室'
sock.send(msg.encode('utf-8'))
except Exception as e:
print(e)
def disConnect(self):
self.server.socket.close()
def run(self):
while True:
#服务器进行开启
readlist,writelist,errorlist = select.select(self.socket_list,[],[],36000)
#当读入列表readlist中没有可读的信息事 即一直没有客户端连接时则退出服务器
if not readlist:
print("没有客户端连接...关闭服务器")
disConntect()
break
for client_socket in readlist:
if client_socket is self.server.socket:#说明有客户进行连接
self.Connect()
else:
#表示有一个client有数据发送到服务器中
disconnect = False;
try:
data = client_socket.recv(4096).decode('utf-8')
data = self.client_names[client_socket] + ':' +data
except socket.error as err:
#有用户掉线
data = self.client_names[client_socket] + '离开聊天室'
disconnect = True;
if disconnect:
#离开聊天室,则将其对应的客户端从读入列表中移除
self.socket_list.remove(client_socket)
print(data)
for sock in self.socket_list:
if(not sock == self.server_socket) and (not sock == client_socket):
try:
sock.send(data.encode('utf-8'));
except Exception as e:
print(e)
#同时将客户端从保存的客户端列表中删除
del self.client_names[client_socket]
else:
print(data)
for sock in self.socket_list:
if (not sock == client_socket) and (not sock == self.server_socket):
try:
sock.send(data.encode('utf-8'))
except Exception as e:
print(e)
'''
***if __name__ == __main
就是当命令运行到chatserver模块文件时,Python解释器把一个特殊变量__name__置为__main__,如果改模块不是直接运行,而是在其他模块中导入使用的时候
if 判断语句会返回false,下面的主程序将不再运行。因此这种if测试可以让一个模块在命令行运行环境下执行main程序的代码,从而实现对该函数的快速测试。
'''
if name == “main”:
#使用本机的hostname
HOST = socket.gethostname()
PORT = 8888
server = ChatServer(HOST,PORT,10)
server.run()
注释讲的听清楚大家可以看下
下面是客户端的代码
import socket,select,threading,sys
class ChatClient():
‘’‘聊天室客户端
‘’’
def __init__(self,host,port):
self.HOST = host
self.PORT = port
self.client_socket = socket.socket()
self.client_socket.connect((self.HOST,self.PORT))
self.client_readlist = [self.client_socket]
def receivemessage(self):
while True:
readlist,writelist,errorlisr = select.select(self.client_readlist,[],[])
if self.client_socket in readlist:
try:
#从服务器接收数据,数据buffer为4096
print(self.client_socket.recv(4096).decode('utf-8'))
except socket.error as err:
print('连接错误...')
exit()
def sendMessage(self):
#发送数据,将客户端用户输入的信息发送出去
while True:
try:
data = input()
except Exception as e:
print('对不起,因为连接错误暂时无法输入信息...')
#exit()
break
try:
self.client_socket.send(data.encode('utf-8'))
except Exception as e:
exit()
def run(self):
#启动接收数据和发送数据线程
thread_recievemsg = threading.Thread(target=self.receivemessage)
thread_recievemsg.start()
thread_sendmsg = threading.Thread(target=self.sendmessage)
thread_sendmsg.start()
if name == “main”:
HOST = socket.gethostname()
RORT = 8888
client= ChatClient(HOST,RORT)
client.run()
这次排版不好 !抱歉抱歉。。。