简体   繁体   中英

Not recieving data python socktes

I am creating a simple chat room server using python and when I send data using I'm not receiving it. The code worked until I sepperated it using functions and classes. I did this so it would be simpler to add a UI

here's my server side code:

import socket
import select
from tkinter import *
import threading

HEADER_LENGTH = 10
IP = socket.gethostbyname('0.0.0.0')
PORT = 1234

class ServerNoGui():

    def __init__(self):
        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

        self.server_socket.bind((IP, PORT))
        self.server_socket.listen()

        self.sockets_list = [self.server_socket]

        self.clients = {}

        print("server started")
        print("Starting thread sub-proccesses...")
        acceptLoop = threading.Thread(target=self.acceptUsers)
        acceptLoop.start()
        recieveLoop = threading.Thread(target=self.manageDataSending)
        recieveLoop.start()
        print("sub-proccesses started!")


    def recieve_message(self, client_socket):
        message_header = client_socket.recv(HEADER_LENGTH)

        if not len(message_header):
            return False

        message_length = int(float(message_header.decode('utf-8').strip()))
        return {'header': message_header, 'data': client_socket.recv(message_length)}

    def acceptUsers(self):
        read_sockets, _x_, exception_sockets = select.select(self.sockets_list, [], self.sockets_list) 

        for notified_socket in read_sockets:
            if notified_socket == self.server_socket:
                client_socket, client_address = self.server_socket.accept()
                print("accepted")

                user = self.recieve_message(client_socket)

                #print(user)
                print("Recieved")

                if(not user):
                    continue

                self.sockets_list.append(client_socket)
                print("added to list")

                self.clients[client_socket] = user
                print("created user")

                print(f"Accepted connection from {client_address[0]}{client_address[1]} username: {user['data'].decode('utf-8')}")

    def manageDataSending(self):
        while True:
            read_sockets, _x_, exception_sockets = select.select(self.sockets_list, [], self.sockets_list)  
            print("point")
            for notified_socket in read_sockets:
                if notified_socket == self.server_socket:
                    print("point 0")
                    self.acceptUsers()
                else:
                    print("point 1")
                    message = self.recieve_message(notified_socket)

                    if(message is False):
                        print(f"Closed connection from {self.clients[notified_socket]['data'].decode('utf-8')}")
                        self.sockets_list.remove(notified_socket)
                        del self.clients[notified_socket]
                        continue

                    else:
                        user = self.clients[notified_socket]

                        type_, data = message['data'].decode("utf-8").split("$")


                        if(type_ == "message"):
                            print(f"Recieved Message from {user['data'].decode('utf-8')} : {message['data'].decode('utf-8')} of type {type_}")
                            for client_socket in self.clients:

                                if client_socket != notified_socket:
                                    client_socket.send(user['header'] + user['data'] + message['header'] + message['data'])

            for notified_socket in exception_sockets:
                sockets_list.remove(notified_socket)
                del clients[notified_socket]    
                print(f"Closed connection from {clients[notified_socket]['data'].decode('utf-8')}")

class serverGUI():
    def __init__():
        window = Tk()
        window.title(f"Chatt.py HOSTING SERVER (IP : {IP} \\\\ HOST : {HOST})")

    def createWidgets(self):
        return False

    def log(self, data):
        return False

    def loop(self):
        window.mainloop()



serverBackend = ServerNoGui()

and here's the client

import socket
import select
import errno
import sys


HEADER_LENGTH = 10

IP = socket.gethostbyname("0.0.0.0")#'192.168.0.40' 
PORT = 1234

my_username = input("Username: ")
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((IP, PORT))
client_socket.setblocking(False)

username = my_username.encode("utf-8");
username_header = f"{len(username):<{HEADER_LENGTH}}".encode("utf-8")

client_socket.send(username_header + username)

while True:
    messageInput = input(f"Me({my_username}) > ")
    message = f"message${messageInput}"

    if(message):
        message = message.encode("utf-8")
        message_header = f"{len(message):<{HEADER_LENGTH}}".encode("utf-8")
        client_socket.send(message_header + message)
        print(f"sent {message_header} : {message}")

    try:
        while True:
            username_header = client_socket.recv(HEADER_LENGTH)
            if(not len(username_header)):
                print("connection closed by server")
                sys.exit()
            username_lenght = int(username_header.decode("utf-8").strip())

            username = client_socket.recv(username_lenght).decode("utf-8")

            message_header = client_socket.recv(HEADER_LENGTH)
            message_length = int(message_header.decode("utf-8").strip())
            messageRaw = client_socket.recv(message_length).decode("utf-8")
            type_, message = messageRaw.split("$")
            if(type_ == message):
                print(f"{username} >> {message}")

    except IOError as e:
        if(e.errno != errno.EAGAIN and e.errno != errno.EWOULDBLOCK):
            print("READ ERR",str(e))
            sys.exit()
        continue

    except Exception as e:
        print("Error".str(e))
        sys.exit()

I decided to try with two clients I get the following output Server:

server started
Starting thread sub-proccesses...
sub-proccesses started!
point
point 0
accepted
Recieved
added to list
created user
Accepted connection from 127.0.0.160338 username: test1
point
point 0
accepted
Recieved
added to list
created user
Accepted connection from 127.0.0.160340 username: test2
point
point 1
Recieved Message from test2 : message$hello of type message
point
point 1
Recieved Message from test1 : message$ of type message
point
point 1
Recieved Message from test1 : message$hello of type message

client1:

Username: test1
Me(test1) > 
sent b'8         ' : b'message$'
Me(test1) > hello
sent b'13        ' : b'message$hello'

client2:

Username: test2
Me(test2) > hello
sent b'13        ' : b'message$hello'

as you can see the messages are sent and recieved by the server but not displayed (I'm not stupid I hit enter a few times).

Your server code is confusing and probably not doing what you thought. First you create a thread to accept connections giving it acceptUsers as its thread function (call this thread A ). However, that function will only run once in that thread , then it will exit after it has visited all of the read_sockets (because there's no while True loop).

Second, your other thread ( B ) is running in manageDataSending -- also executing select , but when a client connects, it's calling acceptUsers . That means on the first connection to your server, there's a "race" between the two threads. It's questionable what will happen next because both are now destined to execute the acceptUsers code at more or less the same time, so the exact order of operations in the two threads is now indeterminate.

It's possible that thread A could run first, handle the server_socket (accept the connection and do the receive) and quit, before thread B enters the select call in acceptUsers . That would leave thread B waiting in the select (in acceptUsers ) until the next time a client connects or sends data.

On the other hand, it's possible that thread A and thread B both get past the select in acceptUsers and both execute the accept call. Then the accept will succeed in one, and block in the other, waiting for a subsequent incoming connection. In either case, your thread B eventually ends up blocked in a place in your code that you didn't expect it to be.

Bottom line: there's no obvious reason for you to have the two separate threads, both doing a select call. It will be much simpler and easier to understand what is going on if create only one thread, and have it execute your socket select in one place, have that place handle the socket notifications for both incoming connections and incoming client data.

One other thing to note: you don't really need to handle the exception_sockets separately. If one of your clients goes away, its entry in the read_sockets list will be signaled as "ready-to-read" and when you attempt to read it, you will get an end-of-file indication (ie zero-length buffer returned).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM