0

I'm trying to learn socket programming and currently have the following server and client code however the problem is that the server and/or client can't send and recieve messages at the same time, they're taking it in turns to send and recieve messages.

I've looked at the below example but the answer doesn't seem to solve the issue, or I'm following it wrong.

Python Socket - Send/Receive messages at the same time

server

import socket
import threading
s = socket.socket()
host = socket.gethostname()
port = 8080
s.bind((host, port))
s.listen(1)
print("Waiting for connections")
conn, addr = s.accept()
print("Client has connected")
conn.send("Welcome to the server".encode())

def recv_msg():
    while True:
        recv_msg = conn.recv(1024)
        if not recv_msg:
            sys.exit(0)
        recv_msg = recv_msg.decode()
        print(recv_msg)

def send_msg():
    send_msg = input(str("Enter message: "))
    send_msg = send_msg.encode()
    conn.send(send_msg)
    print("message sent")

while True:
    send_msg()

t = threading.Thread(target=recv_msg)
t.start()

client

import socket
import threading
s = socket.socket()
host = socket.gethostname()
port = 8080
s.connect((host, port))
print("Connected to the server")
message = s.recv(1024)
message = message.decode()
print(message)

def recv_msg():
    while True:
        recv_msg = s.recv(1024)
        if not recv_msg:
            sys.exit(0)
        recv_msg = recv_msg.decode()
        print(recv_msg)

def send_msg():
    send_msg = input(str("Enter message: "))
    send_msg = send_msg.encode()
    s.send(send_msg)
    print("Message sent")

while True:
    send_msg()

t = threading.Thread(target=recv_msg)
t.start()

I'm ulitmately trying to create a chat app (with kivy) that sort of resembles Whatsapp/Imessage etc, I've not found a tutorial around how to do this (all the ones I've seen are about creating a chatroom) so if anyone's seen one that would be appreciated.

Callum
  • 195
  • 2
  • 22
  • As an aside, `send_msg.encode()` uses your default encoding which will vary by machine. Instead, pick an encoding that everyone uses on the chat channel `send_msg.encode('utf-8')`. – tdelaney Feb 24 '20 at 20:10
  • to send and receive at the same time you may need two separated threads. One only to send from server to client, and second only to send from client to server. Or you have to use one thread and client should periodically send request with new message or empty message (if client has nothing to send) and after that get new answer or empty answer (if server has nothing to send). This way it will get new value from serve and server doesn't need to send it in separated socket. – furas Feb 24 '20 at 20:18
  • I'm not sure I understand exactly what you mean here – Callum Feb 24 '20 at 21:34
  • one thread has to send only in one direction (client->server), other thread has to send only in other direction (server->client). Or in one thread you send `client->server` and after that `server->client` and repeate it again and again with constant delay. If there is nothing to send then send empty message so it always sends something (because other side will try to receive something). – furas Feb 24 '20 at 21:58
  • 1
    BTW: In current code in client and server you have to start thread before you run `while True: send_msg()`. – furas Feb 24 '20 at 22:00

1 Answers1

0

In client and server you have to start threads before you run loops while True: send_msg()

t = threading.Thread(target=recv_msg)
t.start()

while True:
    send_msg()

EDIT:

server.py

import socket
import threading
import sys

# --- functions ---

def recv_msg():
    while True:
        recv_msg = conn.recv(1024)
        if not recv_msg:
            sys.exit(0)
        recv_msg = recv_msg.decode()
        print(recv_msg)

def send_msg():
    while True:
        send_msg = input(str("Enter message: "))
        send_msg = send_msg.encode()
        conn.send(send_msg)
        print("message sent")

# --- main ---

host = socket.gethostname()
port = 8080

s = socket.socket()
s.bind((host, port))
s.listen(1)

print("Waiting for connections")
conn, addr = s.accept()

print("Client has connected")
conn.send("Welcome to the server".encode())

# thread has to start before other loop
t = threading.Thread(target=recv_msg)
t.start()

send_msg()

client.py

import socket
import threading
import sys

# --- functions ---

def recv_msg():
    while True:
        recv_msg = s.recv(1024)
        if not recv_msg:
            sys.exit(0)
        recv_msg = recv_msg.decode()
        print(recv_msg)

def send_msg():
    while True:
        send_msg = input(str("Enter message: "))
        send_msg = send_msg.encode()
        s.send(send_msg)
        print("Message sent")

# --- main ---

host = socket.gethostname()
port = 8080

s = socket.socket()
s.connect((host, port))

print("Connected to the server")

message = s.recv(1024)
message = message.decode()
print(message)

# thread has to start before other loop
t = threading.Thread(target=recv_msg)
t.start()

send_msg()
furas
  • 134,197
  • 12
  • 106
  • 148
  • I've tried this but it keeps stalling at the input part of ```send_msg``` waiting for a user input and can't recieve messages until it has completed the ```send_msg``` function (i.e a message has been sent) – Callum Feb 24 '20 at 22:46
  • you have to use `send_msg()` after `thead ` in both - in client and in server. – furas Feb 24 '20 at 22:57
  • This isn't working, the code is still pausing at the ```send_msg``` function, waiting for user input before it recieves (and prints) and message. – Callum Feb 25 '20 at 19:18
  • which `send_msg` - in client or in server ? Both have it and both wait for user input. Maybe it wait because other side didn't send message - both use `input()`. What system do you use Windows, Linux, Mac? I tested on LInux. – furas Feb 25 '20 at 21:46
  • In both the client and server. I'm using Windows – Callum Feb 25 '20 at 21:53
  • I don't use Windows to test it but maybe problem is not socket but how works console and standard output/input in Windows. Maybe it needs `sys.stdout.flush()` after `print()` to force standard outut to dislay it. But probably if you will write receiverd message in file or display in some GUI then it will work put text at once because system will not block it. – furas Feb 25 '20 at 22:53
  • Ok thanks for trying to help, I am hoping to understand how to fully implement sockets in my chat app before trying to implement it and was hoping to use the command line for this, rather than building a GUI – Callum Feb 27 '20 at 19:41