I am writing a simple python socket program where client is sending a string to server and server says how many vowels in that string then send it back to client and client prints the output. Now, I do not know why it is not showing connection ended
after sending end
message. If I remove the \n
from there the message appear in the same line for all except MESSAGE RECEIVED
appear in the next line after Not enough vowel
. Now how I can show CONNECTION ENDED
also keeping all the messages in separate line.
server.py
import socket
FORMAT = 'utf-8'
PORT = 5050
HOST = socket.gethostbyname(socket.gethostname())
ADDR = (HOST,PORT)
DISCONNECTED_MESSAGE = 'End'
server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(ADDR)
server.listen()
print("[LISTENING] server is listenning")
while True:
conn,addr = server.accept()
connected = True
while connected:
msg = conn.recv(2048).decode(FORMAT)
if msg == DISCONNECTED_MESSAGE:
connected = False
conn.send("CONNECTION ENDED".encode(FORMAT))
else:
vowel_count = 0
for chr in msg:
if chr in "aeiouAEIOU":
vowel_count = 1
if vowel_count == 0:
conn.send("Not enough vowels".encode(FORMAT))
elif vowel_count <= 2:
conn.send("Enough Vowel I guess\n".encode(FORMAT))
else:
conn.send("Too many vowels\n".encode(FORMAT))
conn.send("MESSAGE RECEIVED\n".encode(FORMAT))
conn.close()
client.py
import socket
PORT = 5050
HOST = socket.gethostbyname(socket.gethostname())
ADDR = (HOST,PORT)
FORMAT = 'utf-8'
DISCONNECTED_MESSAGE = 'End'
client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(ADDR)
def send(msg):
message = msg.encode(FORMAT)
client.send(message)
print(client.recv(2048).decode(FORMAT))
send("Nymphs cry gypsy rhythms Why Mythy nymphs cry ?Why nymphs flyby ?")
send("Nymphs cry gypsy rhythms hello Why Mythy nymphs cry ?Why nymphs flyby ?")
send("Nymphs cry gypsy rhythms Why Mythy nymphs cry ?Why nymphs flyby ? hello hello everybody good evening")
send(DISCONNECTED_MESSAGE)
CodePudding user response:
The issue here is that TCP is a stream protocol, not a packet protocol. The reader does not get things in the same blocks you write. In your particular case, your server is sending two responses for each input (number of vowels and "MESSAGE RECEIVED"). Sometimes, those two messages get packed together and received in one read by the client, but sometimes, you only read the vowel evaluation by itself. Your client send
function then returns, and sends its next message. It then reads "MESSAGE RECEIVED", even those the server has already queued up two more lines. By the time it gets to the end, it exits even though "CONNECTION ENDED" is still queued up.
The real solution is to have some "end of transmission" signal that your server sends when it is finished, like some unused control character. Your client should then continue to read until it gets a string that ends with your "end of transmission" signal.
The short term fix is just to have your server concatenate all the strings it wants to send into one conn.send
call. Technically, TCP is allowed to break that up into smaller chunks for transmission, so it could still fail, but in practice that doesn't happen.