Python学习:Socket编程——多客户端通信聊天室

  最近学习Python,又需要学习一下网络编程的一些知识,写了一个简单的聊天室的程序。程序分为两个python文件,一个是server.py,另一个是client.py。

  Socket编程的流程如下图所示:

  

  

  服务端:

  1.服务端需要创建一个socket对象。(socket())

  2.为这个socket对象绑定ip地址和端口号。(bind())

  3.让socket对象进入监听状态,传入的参数是指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了。(listen())

  4.在while True循环里接收客户端发送过来的连接请求,如果没有连接请求该循环会被阻塞。(accept()是否返回了值)

  5.服务端接收到客户端发送过来的连接请求后(accept()有了返回值),返回一个新的socket对象和list类型的地址,这个list第0项是记录的ip,第1项是记录的端口号。

  6.之后客户端会通过send(),sendall()等方法发送具体的数据给服务端,后续服务端与客户端会通过accept()返回的新socket对象来通信。这个新的socket对象要放在一个之前的while True循环下的一个新的while True循环来使用recv()获取消息。(recv(),send(),sendall())

  

  客户端:

  1.客户端创建一个socket对象。(socket())

  2.客户端发起一个连接请求。(connect())  ====>对应服务端的4.

  3.客户端发送数据。(send(),sendall())    ====>对应服务端的6.

  通信的过程如上所述,但是还需要注意一些细节。socket通信通过byte来传递,字符串需要通过encode()编码成byte型才能传输。接收端需要将byte通过decode()解码才能转换为字符串。如果要传输对象,则需要导入pickle模块,通过pickle.dumps(object)来转化为可以传输的类型,通过pickle.loads(object)来还原回对象。

  

  为了实现多客户端连接的功能,需要引入多线程。每当一个客户端发起连接时,就创建一个新的线程,这个线程就负责为这个客户端进行通信。这样就可以支持多线程的通信。userList是一个list,每当有客户端连接到服务端,就会将这一对连接的socket添加到list当中。这样之后该线程中接收到该客户端发送的信息后,会遍历这个list的每个元素,实现向每一个客户端转发该客户端发送的消息。

1 while True:
2     conn, addr = socket_server.accept()
3     # conn为新的socket对象,与服务器连接后的后续操作由conn去处理
4     userDict[conn] = addr
5     userList.append(conn)
6     thread = threading.Thread(target=newClientConnection, args=(conn, addr))
7     thread.start()

  

1  while True:
2         words_byte = conn.recv(1024)
3         words = words_byte.decode()
4         print(words)
5         for c in userList:
6             c.sendall(words.encode())

  为了实现客户端可以接收其他客户端发送的消息,同时又可以多次发送新的消息,需要创建两个线程,一个是接收消息的线程,一个是发送消息的线程。

1 thread_send = threading.Thread(target=sendMessage, args=(socket_client, name))
2 thread_send.start()
3 thread_receive = threading.Thread(target=receiveMessage, args=(socket_client,))
4 thread_receive.start()
def sendMessage(socket_client, name):
    while True:
        words = input()
        message = name + "  :   " + words
        socket_client.sendall(message.encode())
def receiveMessage(socket_client):
    while True:
        dataFromServer_byte = socket_client.recv(1024)
        str = dataFromServer_byte.decode()
        print(str)

  需要注意threading模块创建线程时,"target="需要填入函数名,"args="需要填入该函数的参数,并且是以元组的形式填入,如果只有一个参数,需要在该参数后加一个”,“。

  项目中Git知识的总结:

  获取历史提交代码的版本

git log #查看历史提交记录和版本号
git branch 新分支名 版本号 #创建新分支,并且该新分支即为版本号对应版本的代码
git checkout 新分支名#切换到该新分支            

  

  合并本地版本其他分支到master分支

git checkout master
git merge 分支名

猜你喜欢

转载自www.cnblogs.com/sheeks/p/9233342.html