I'm new to socket programming and trying to get back into python. I wanted to write a simple TCP program which will continuously maintain a connection until some end state is reached, in this case "close" is sent by the client.
This works fine for the first iteration, but it freezes on the second thing I send and I'm not sure why. Could someone please explain why my program freezes or how better implement this?
TCPServer.py
from socket import *
serverPort = 12000
serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
serverSocket.bind(('', serverPort))
serverSocket.listen(1)
print('The server is ready to recieve')
while True:
connectionSocket, addr = serverSocket.accept()
sentence = connectionSocket.recv(1024).decode()
if(sentence == "close"):
connectionSocket.close()
capSentence = sentence.upper()
connectionSocket.send(capSentence.encode())
TCPClient.py
from socket import *
serverName = 'localhost'
serverPort = 12000
clientSocket = socket(AF_INET, SOCK_STREAM)
clientSocket.connect((serverName, serverPort))
while(1):
sentence = raw_input('input sentence: ')
if(sentence == "close"):
break
clientSocket.send(sentence.encode())
retSentence = clientSocket.recv(1024)
print('From server; ', retSentence.decode())
clientSocket.close()
There are multiple problems with the server. I'll try to point out what I see.
It freezes on the second thing you send because the server never attempts to read from the client socket a second time if the received data is not equal to "close"
. You need another loop to accomplish this, such as:
while True:
connectionSocket, addr = serverSocket.accept()
while True:
sentence = connectionSocket.recv(1024).decode()
if sentence == "close": break
capSentence = sentence.upper()
connectionSocket.send(capSentence.encode())
connectionSocket.close()
Additionally, note that the server runs through the loops synchronously, and so it cannot accept a second connection until the first one is closed.
Finally, you are missing error handling code. The whole server will crash if a client prematurely disconnects.
If your goal is to have the server only handle a single connection and then terminate, the simplest solution is to move the accept()
call outside of the main loop (otherwise you wait for a new connection on each iteration).
connectionSocket, addr = serverSocket.accept()
# Destroy the server socket; we don't need it anymore since we are not
# accepting any connections beyond this point.
serverSocket.close()
while True:
sentence = connectionSocket.recv(1024).decode()
if(sentence == "close"):
connectionSocket.close()
break
capSentence = sentence.upper()
connectionSocket.send(capSentence.encode())
You've got just a single socket connection going on in the client but in the server code you have the accept
call inside the while loop. Move it outside the loop.
There's more than this that is wrong with the code though but that kinda depends on where you want to go from here