【问题标题】:socket chat room - python 3.7套接字聊天室 - python 3.7
【发布时间】:2019-07-03 01:56:42
【问题描述】:

这是我一直在开发的一个 python 聊天室,它可以让你通过 python 与同一网络上的其他人聊天

主持人:

import socket
import sys
import time

s = socket.socket()
host = socket.gethostname()
port = 8080
s.bind((host,port))
print("")
print("Sever adress is", host)
print("")
name = input(str("Please enter your username : "))
s.listen(1)
print("")
print("Waiting for any incoming connections ... ")
print("")
conn, addr = s.accept()
print("Recieved connection")

#connection done ###

s_name = conn.recv(1024)
s_name = s_name.decode()
print("")
print(s_name, "has connected to the chat room")
print("")
conn.send(name.encode())

## messaging loop ##

while 1:
    message = input(str("Please enter enter your message : "))
    print("")
    conn.send(message.encode())
    message = conn.recv(1024)
    message = message.decode()
    print("")
    print(name,": ",message)
    print("")

客户:

import socket
import sys
import time

print("Welcome to python chat ")
print("")
print("Initiallsing....")
time.sleep(1)

s = socket.socket()
print("")
host = input(str("Please enter server adress : "))
print("")
name = input(str("Please enter your name : "))
port = 8080
print("")
time.sleep(1)
s.connect((host,port))
print("Connected...")

## Conection done ##

s.send(name.encode())
s_name = s.recv(1024)
s_name = s_name.decode()
print("")
print( s_name, "has joined the chat room ")

while 1:
    message = s.recv(1024)
    message = message.decode()
    print("")
    print(name,": ",message)
    print("")
    message = input(str("Please enter your enter message : "))
    print("")
    s.send(message.encode())

我有两个问题,第一个问题是它一次只允许一个人说话,我的意思是如果你先发送一条消息,你将无法发送另一条消息,直到另一个人有回应。第二个问题是此代码仅适用于 2 个用户,我希望它适用于多个用户

编辑:

也可以有人准确地给出一个适当的解决方案,而不是告诉我重新开始,因为我花了很长时间才弄清楚如何在这个地方制作这个系统。

谢谢

【问题讨论】:

  • 你应该先试试谷歌。你更有可能得到更深入的答案。 google.com/search?q=python+chat+program+example
  • @JohnnyMopp 我看过谷歌,但我不知道如何将它放入我的代码中
  • 您需要创建两个单独的线程用于发送和接收。您编写循环的方式不能同时用于双向通信。因为在发送消息后,您的循环正在等待接收某些内容。
  • @shariful 你能告诉我怎么做吗
  • 我已经在下面发布了一个答案,请看一下。 @system123456

标签: python python-3.x sockets tcp


【解决方案1】:

您需要为发送和接收创建两个单独的线程。您编写循环的方式不能同时用于双向通信。因为在发送消息后,循环正在等待接收某些东西。 [如果您想通过 Internet 运行代码,请将 localhost 替换为 HOST = 'localhost' 行中所需的 IP 地址] 让我分享一个解决方案(这是我在上本科网络课程时所做的示例解决方案):

我已经在 Linux 机器 (Ubuntu 18.04) 上测试了代码。我有学生在他们的 Mac 上成功运行了这个。我不确定它是否在 Windows 机器上运行。即使它不能在 Windows 机器上运行,一些小的修改也应该可以解决问题。

服务器端代码(您需要先运行此代码):chatServerDuplex.py

# Import socket module
from socket import *
import threading
import sys # In order to terminate the program

FLAG = False  # this is a flag variable for checking quit

# function for receiving message from client
def recv_from_client(conn):
    global FLAG
    try:
        # Receives the request message from the client
        while True:
            if FLAG == True:
                break
            message = conn.recv(1024).decode()
            # if 'q' is received from the client the server quits
            if message == 'q':
                conn.send('q'.encode())
                print('Closing connection')
                conn.close()
                FLAG = True
                break
            print('Client: ' + message)
    except:
        conn.close()


# function for receiving message from client
def send_to_client(conn):
    global FLAG
    try:
        while True:
            if FLAG == True:
                break
            send_msg = input('')
            # the server can provide 'q' as an input if it wish to quit
            if send_msg == 'q':
                conn.send('q'.encode())
                print('Closing connection')
                conn.close()
                FLAG = True
                break
            conn.send(send_msg.encode())
    except:
        conn.close()


# this is main function
def main():
    threads = []
    global FLAG

    # TODO (1) - define HOST name, this would be an IP address or 'localhost' (1 line)
    HOST = 'localhost'
    # TODO (2) - define PORT number (1 line) (Google, what should be a valid port number)
    # make sure the ports are not used for any other application
    serverPort = 6789

    # Create a TCP server socket
    #(AF_INET is used for IPv4 protocols)
    #(SOCK_STREAM is used for TCP)
    # TODO (3) - CREATE a socket for IPv4 TCP connection (1 line)
    serverSocket = socket(AF_INET, SOCK_STREAM)

    # Bind the socket to server address and server port
    # TODO (4) - bind the socket for HOSR and serverPort (1 line)
    serverSocket.bind((HOST, serverPort))

    # Listen to at most 1 connection at a time
    # TODO (5) - listen and wait for request from client (1 line)
    serverSocket.listen(1)

    # Server should be up and running and listening to the incoming connections
    print('The chat server is ready to connect to a chat client')
    # TODO (6) - accept any connection request from a client (1 line)
    connectionSocket, addr = serverSocket.accept()
    print('Sever is connected with a chat client\n')

    t_rcv = threading.Thread(target=recv_from_client, args=(connectionSocket,))
    t_send = threading.Thread(target=send_to_client, args=(connectionSocket,))
    # call the function to receive message server
    #recv_from_server(clientSocket)
    threads.append(t_rcv)
    threads.append(t_send)
    t_rcv.start()
    t_send.start()

    t_rcv.join()
    t_send.join()


    # closing serverScoket before exiting
    print('EXITING')
    serverSocket.close()
    #Terminate the program after sending the corresponding data
    sys.exit()


# This is where the program starts
if __name__ == '__main__':
    main()

客户端代码:chatClientDuplex.py

from socket import *
import threading
import sys


FLAG = False  # this is a flag variable for checking quit

# function for receiving message from client
def send_to_server(clsock):
    global FLAG
    while True:
        if FLAG == True:
            break
        send_msg = input('')
        clsock.sendall(send_msg.encode())

# function for receiving message from server
def recv_from_server(clsock):
    global FLAG
    while True:
        data = clsock.recv(1024).decode()
        if data == 'q':
            print('Closing connection')
            FLAG = True
            break
        print('Server: ' + data)

# this is main function
def main():
    threads = []
    # TODO (1) - define HOST name, this would be an IP address or 'localhost' (1 line)
    HOST = 'localhost'  # The server's hostname or IP address
    # TODO (2) - define PORT number (1 line) (Google, what should be a valid port number)
    PORT = 6789        # The port used by the server

    # Create a TCP client socket
    #(AF_INET is used for IPv4 protocols)
    #(SOCK_STREAM is used for TCP)
    # TODO (3) - CREATE a socket for IPv4 TCP connection (1 line)
    clientSocket = socket(AF_INET, SOCK_STREAM)

    # request to connect sent to server defined by HOST and PORT
    # TODO (4) - request a connection to the server (1 line)
    clientSocket.connect((HOST, PORT))
    print('Client is connected to a chat sever!\n')



    # call the function to send message to server
    #send_to_server(clientSocket)
    t_send = threading.Thread(target=send_to_server, args=(clientSocket,))
    # call the function to receive message server
    #recv_from_server(clientSocket)
    t_rcv = threading.Thread(target=recv_from_server, args=(clientSocket,))
    threads.append(t_send)
    threads.append(t_rcv)
    t_send.start()
    t_rcv.start()

    t_send.join()
    t_rcv.join()

    print('EXITING')
    sys.exit()

# This is where the program starts
if __name__ == '__main__':
    main()

【讨论】:

    【解决方案2】:

    您的第一个问题可能是由于默认情况下 python 套接字是阻塞的。 这意味着,例如,在message = s.recv(1024) 行上,您的程序将继续侦听,并且在收到某些内容之前不会继续执行脚本的其余部分。

    如果您希望两个人能够同时接收和发送,您可能需要研究非阻塞套接字和一些异步编程。 官方文档中的这个操作指南可能会对您有所帮助:https://docs.python.org/2/howto/sockets.html#non-blocking-sockets

    【讨论】:

    • 好的,我会查看文档并尝试理解它
    • 我已阅读,但我不知道在我的代码中包含解决方案的位置
    • @system123456 如果您只是在寻找解决方案并将其包含在代码中的某个位置,那将很困难。请尝试理解流程。代码是如何工作的。
    • @yaken 好的,我会尝试,但您找到解决我第二个问题的方法了吗?
    【解决方案3】:

    System123456 问题是当服务器侦听并且客户端连接到它时,您构建了一个客户端-服务器系统。尝试查看点对点系统,而不是每个节点都是平等的。要构建聊天室,您可能需要查看 DHT 节点。

    【讨论】:

    • 你知道我的第二个问题的解决方案吗?
    • 是的,但这并不能解决您的整体问题。关于非阻塞套接字的注释可以帮助您的服务器处理多个客户端。但真正的问题不是你的代码,而是你的架构。如果你想建立一个聊天系统,你的客户需要互相交谈。使用客户端-服务器架构,您的客户端只与服务器对话。这就是为什么我建议点对点。 Python 很容易构建一个 DHT 点对点系统,它可以满足您的需求。
    猜你喜欢
    • 2018-03-22
    • 1970-01-01
    • 2019-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-17
    • 1970-01-01
    • 2022-01-05
    相关资源
    最近更新 更多