【问题标题】:Python P2P 1-to-1 chat programmingPython P2P 1对1聊天编程
【发布时间】:2019-06-28 09:31:45
【问题描述】:

我目前正在尝试制作一个 Python 程序,其中连接到不同服务器的两台计算机可以相互发送消息。 以下是我的代码:

服务器.py:

import sys
import socket

def main():

    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind(('', 11111))
        s.listen(1)

        while True:
            (conn, addr) = s.accept() 

            while True:
                received = conn.recv(1024)
                if received == '':
                    break
                else:
                    print(received.decode())

                send_msg = input().replace('b', '').encode()
                if send_msg == ' ':
                    break
                else:
                    conn.sendall(send_msg)
                    print("sent")

if __name__ == '__main__':
    main()

客户端.py:

import sys
import socket
import select

def main():
    if len(sys.argv) is not 3:
        print("usage: %s [ip adress][port] " % sys.argv[0] )
        return(-1)
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.connect((sys.argv[1], int(sys.argv[2])))

        while True:
            s_msg = input().replace('b', '').encode('utf-8')
            if s_msg == '':
                break 
            else:
                s.sendall(s_msg)
            r_msg = s.recv(1024)
            if r_msg == '':
                break
            else:
                print(r_msg.decode())

if __name__ == '__main__':
    main()

当我通过从 server.py 发送消息来执行代码时,在我尝试从客户端向服务器发送消息之前,该消息不会发送到客户端。以下是结果示例:

有人知道我的代码有什么问题吗?

如果需要任何额外信息,请告诉我。提前谢谢你。

【问题讨论】:

    标签: python python-3.x p2p python-sockets


    【解决方案1】:

    我能够使用以下代码实现简单的 P2P 聊天程序:

    server.py

    import sys
    import socket
    import threading
    
    #TODO: exit program when client ends the connection
    def connect(conn):
        while True:
            received = conn.recv(1024)
            if received ==' ':
                pass
            else:
                print(received.decode())
    
    def sendMsg(conn):
        while True:
            send_msg = input().replace('b', '').encode()
            if send_msg == ' ':
                pass
            else:
                conn.sendall(send_msg)
    
    if __name__ == '__main__':
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.bind(('', 11111))
        s.listen()
        (conn, addr) = s.accept() 
        thread1 = threading.Thread(target = connect, args = ([conn]))
        thread2 = threading.Thread(target = sendMsg, args = ([conn]))
        thread1.start()
        thread2.start()
        thread1.join()
        thread2.join()
    

    client.py

    import sys
    import socket
    import threading
    
    #TODO:end connection with 'exit'
    def connect(s):
        while True:
            r_msg = s.recv(1024)
            if not r_msg:
                break
            if r_msg == '':
                pass
            else:
                print(r_msg.decode())
    
    def receive(s):
        while True:
            s_msg = input().replace('b', '').encode('utf-8')
            if s_msg == '':
                pass
            if s_msg.decode() == 'exit':
                print("wan exit")
                break
            else:
                s.sendall(s_msg)
    
    if __name__ == '__main__':
        if len(sys.argv) is not 3:
            print("usage: %s [ip adress][port] " % sys.argv[0] )
            sys.exit(0)
    
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.connect((sys.argv[1], int(sys.argv[2])))
        thread1 = threading.Thread(target = connect, args = ([s]))
        thread2 = threading.Thread(target = receive, args = ([s]))
        thread1.start()
        thread2.start()
        thread1.join()
        thread2.join()
    

    【讨论】:

      【解决方案2】:

      在您的代码中,input() 是一个阻塞函数,表示在您按 Enter 之前执行停止。

      所以需要发送消息来执行接收部分。

      为了处理问题,您可以使用question中提到的非阻塞输入函数。

      或者可能使用多线程代码:一个线程读取使用输入和发送,另一个线程接收和打印。


      编辑:

      如果由于这一行而没有收到任何消息,服务器将无法发送消息:

                  received = conn.recv(1024)
      

      如果客户端仍然连接并且什么都不发送,服务器将在这条线上等待。因此,您需要在服务器端接收一条消息才能访问发送部分。

      您可以尝试使用non-blocking sockets 来防止这种行为。

      【讨论】:

      • 但是我对阻塞函数部分不太了解。你的意思是当我执行 server.py 时,while-loop 不会运行?
      • 当您运行 server.py 时,应用程序将在此行等待:send_msg = input().replace('b', '').encode(),直到您在服务器终端中按 Enter。
      • 对不起,我刚刚发现意识到你的问题,由于这种情况,你不能在没有接收的情况下向服务器发送消息:if s_msg == '': 在服务器端。我将编辑我的答案
      • 当我输入消息“来自服务器的你好”并按下“Enter”时,它仍然不会发送到客户端,直到客户端发送消息到服务器。
      • if s_msg= ' ': 有什么问题?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多