Send/Receive messages at the same time socket pyth

2019-05-10 17:47发布

问题:

I have been working on a simple python socket chat room where the client and server can send messages to each other. The issue that I came across was that the server and client can only send one message at a time. I want it to work like any other chat room, where I could receive a message when I am sending a message, any help will help greatly

Server.py

import socket
import sys

s = socket.socket()
host = socket.gethostname()
print(" server will start on host : ", host)
port = 8080
s.bind((host,port))
name = input(str("Please enter your username: "))
print("")
print("Server is waiting for incoming connections")
print("")
s.listen(1)
conn, addr = s.accept()
print("Recieved connection")
print("")
s_name = conn.recv(1024)
s_name = s_name.decode()
print(s_name, "has joined the chat room")
conn.send(name.encode())

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

Client.py

import socket
import sys

s = socket.socket()
host = input(str("Please enter the hostname of the server : "))
port = 8080
s.connect((host,port))
name = input(str("Please enter your username : "))
print(" Connected to chat server")

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(s_name, ":" ,message)
    print("")
    message = input(str("Please enter your message: "))
    message = message.encode()
    s.send(message)
    print("Sent")
    print("")

回答1:

CaSper has given me the server code where multiple clients can connect to the server but the problem now is that the clients can not talk to each other …

That's primarily because your client wants s_name = s.recv(1024), while CaSper's server doesn't send its name. Here's a variant of your client (expecting host and port as command arguments) which works with CaSper's server and also addresses your original issue (client can only send one message at a time) by using separate threads:

import socket
import sys

s = socket.socket()
s.connect((sys.argv[1], int(sys.argv[2])))
name = input(str("Please enter your username : "))
print(" Connected to chat server")
s.send(name.encode())

def receive_and_print():
    for message in iter(lambda: s.recv(1024).decode(), ''):
        print(":", message)
        print("")
import threading
background_thread = threading.Thread(target=receive_and_print)
background_thread.daemon = True
background_thread.start()

while 1:
    s.send(input("Please enter your message: ").encode())
    print("Sent")
    print("")

Note that CaSper's server has a series of deficiencies:

  1. Even now that your clients can send messages at any time, the server waits for a message from one by one client, i. e. when it waits for client A, client B can send a message, but the server receives and broadcasts it only after client A has sent something.
  2. It doesn't handle client disconnects.
  3. It goes into a busy loop when all clients disconnected.

For a better server example, see the question Handle multiple requests with select.

… could you possibly change my server so that it works …

Here's a variant of your server which works with this client, also using separate threads for input and reception:

import socket
import sys

s = socket.socket()
host = socket.gethostname()
print(" server will start on host : ", host)
port = 8080
s.bind((host,port))
name = input(str("Please enter your username: "))
print("")
print("Server is waiting for incoming connections")
print("")
s.listen(1)
conn, addr = s.accept()
print("Recieved connection")
print("")
s_name = conn.recv(1024)
s_name = s_name.decode()
print(s_name, "has joined the chat room")

def input_and_send():
    while 1:
        message = name+" : "+input(str("Please enter your message: "))
        conn.send(message.encode())
        print("Sent")
        print("")
import threading
background_thread = threading.Thread(target=input_and_send)
background_thread.daemon = True
background_thread.start()

for message in iter(lambda: conn.recv(1024).decode(), ''):
    print(s_name, ":", message)
    print("")


回答2:

Did you try to used Threading module or time module maybe.This happen because both scripts send messages in same time.Try Ex(Client wait message from server frist, then client sent message to server).



回答3:

THIS IS SERVER

import socket
import threading as th

def accept_client():
    while True:
        # ACCEPTING    
        cli_sock, cli_add = ser_sock.accept()
        uname = cli_sock.recv(1024)
        CONN_LIST.append((uname, cli_sock))
        print('%s is now connected' %uname)

def broadcast_usr():
    while True:
        for i in range(len(CONN_LIST)):
            try:
                data = CONN_LIST[i][1].recv(1024)
                if data:
                    b_usr(CONN_LIST[i][1], CONN_LIST[i][0], data)
            except Exception as x:
                print(x.message)
                break

def b_usr(cs_sock, sen_name, msg):
    for i in range(len(CONNECTION_LIST)):
        if (CONN_LIST[i][1] != cs_sock):
            CONN_LIST[i][1].send(sen_name)
            CONN_LIST[i][1].send(msg)


if __name__ == "__main__":    
    CONN_LIST = []

    # SOCKET
    ser_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # BINDING
    host = '192.168.x.x' #LOCAL HOST
    port = 4444
    ser_sock.bind((host, port))

    # LISTENING    
    ser_sock.listen(1)
    print('Chat server started on port : ' + str(port))

    thread_ac = th.Thread(target = accept_client)
    thread_ac.start()

    thread_bs = th.Thread(target = broadcast_usr)
    thread_bs.start()