I have server and client code in python in which client sends a request message to server and wait for the response. I have the server code to close the connection when the client doesn't send a proper request. When the server closes the request, the client still is listening forever for the response.
Below is the code
server.py
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind((host, port))
s.listen(1)
while True:
c, addr = s.accept()
# Receive request
data = c.recv(1024)
if data != 'something'
c.close()
else
c.sendall("message"+"End")
c.close()
s.close()
Client.py
End='End'
def recv_end(the_socket):
# Snippet from http://code.activestate.com/recipes/408859-socketrecv-three-ways-to-turn-it-into-recvall/
total_data=[];data=''
while True:
data=the_socket.recv(8192)
if End in data:
total_data.append(data[:data.find(End)])
break
total_data.append(data)
if len(total_data)>1:
#check if end_of_data was split
last_pair=total_data[-2]+total_data[-1]
if End in last_pair:
total_data[-2]=last_pair[:last_pair.find(End)]
total_data.pop()
break
return ''.join(total_data)
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((host, port))
s.send("some_request")
data = s.recv_end(1024)
print "<---- " + str(data)
s.close()
I'm new to python and wondering if there is a way for the client to know that the server closed the connection and terminate.
I understand that the client would disconnect if I use normal s.recv(1024). But in my case, I need to send large data to the client so I have used a different function I found from http://code.activestate.com/recipes/408859-socketrecv-three-ways-to-turn-it-into-recvall/.
Is it like the server sends a empty string reply during the close of a connection and in my case, it would send a empty string without the end limiter and hence the client is listening forever ?
When you have a loop with recv or anything that reads from a socket or a pipe, you should stop reading as soon as you get a buffer with len 0 :
while True:
data=the_socket.recv(8192)
if len(data) == 0: break
...
Related
I'm quite new to socket programming, and I was wondering why the client stops responding after I send 3 messages to the server. Basically I send a message twice and the server responds to the client. The third time, the client just runs infinitely and the server doesn't receive anything.
Does it have something to do with overload? How does that work, especially with socket.listen()
Here is the code for reference:
client.py
# Import socket module
import socket
# Create a socket object
s = socket.socket()
# Define the port on which you want to connect
port = 12345
# connect to the server on local computer
s.connect(('127.0.0.1', port))
while True:
msg = input("Enter your message: ")
if msg != "quit":
s.send((msg).encode())
else:
# close the connection
s.close()
# receive data from the server
new_msg = (s.recv(1024).decode())
print ("[CLIENT]: ", new_msg)
server.py
# first of all import the socket library
import socket
# next create a socket object
s = socket.socket()
print ("Socket successfully created")
# reserve a port on your computer in our
# case it is 12345 but it can be anything
port = 12345
# Next bind to the port
# we have not typed any ip in the ip field
# instead we have inputted an empty string
# this makes the server listen to requests
# coming from other computers on the network
s.bind(('', port))
print ("socket binded to %s" %(port))
# a forever loop until we interrupt it or
# an error occurs
while True:
# put the socket into listening mode
s.listen(20)
print ("socket is listening")
# Establish connection with client.
c, addr = s.accept()
print('Got connection from', addr)
msg = c.recv(1024).decode()
if msg == "quit":
# Close the connection with the client
c.close()
else:
print ("[SERVER]: Recieved data: ", msg)
print ("[SERVER]: sending", msg)
c.send((msg).encode())
You still need a better understanding on how a listening socket works:
it listens only once
it accepts only once per connection
it can read and send as many packets as required until either side closes the connection
at that point (and for a single threaded server) it is ready to accept a new connection
You server.py should become:
...
s.bind(('', port))
print ("socket binded to %s" %(port))
# put the socket into listening mode
s.listen(20)
print ("socket is listening")
# a forever loop until we interrupt it or
# an error occurs
while True:
# Establish connection with client.
c, addr = s.accept()
print('Got connection from', addr)
while True:
msg = c.recv(1024).decode()
if len(msg) == 0: # the client does not send anything but just closes its side
# Close the connection with the client
c.close()
print('Client disconnected')
break
else:
print ("[SERVER]: Recieved data: ", msg)
print ("[SERVER]: sending", msg)
c.send((msg).encode())
A small fix for the client side:
...
if msg != "quit":
s.send((msg).encode())
else:
# close the connection
s.close()
break # break out of the loop after closing connection
But that is not all: TCP is a stream protocol. You should be prepared for packets send from one side to be splitted or re-assembled before reaching other side. The only guarantee is that bytes arrive in same order that they were send, but not necessarily in same packets.
I have the following case:
SERVER
sock = socket.socket()
sock.bind((hostaddr, port))
sock.listen(backlog)
print(f'Server listenning on {hostaddr}:{port}')
while True:
client_sock, client_address = self.sock.accept()
print(f'Incoming connection from {client_address[0]}:{client_address[1]}')
while True:
data = client_socket.recv(buffer_size)
if not data:
break
print(f'Received "{data.decode()}" from {client_address[0]}:{client_address[1]}')
reply = f'Server: I got the message "{data.decode()}"'.encode()
client_socket.sendall(reply)
client_socket.close()
CLIENT
sock = socket.socket()
sock.connect(server_address)
sock.sendall('Lorem Ipsum'.encode())
while True:
data = sock.recv(buffer_size)
if not data:
break
print(data.decode())
sock.close()
I first start the server, then I start the client, and I get the following logs:
SERVER
Server listening on 172.16.0.110:8081
Incoming connection from 172.16.0.110:62388
Received "Lorem Ipsum" from 172.16.0.110:62388
CLIENT
Server reply: I got the message "Lorem Ipsum"
I wanted to get the server reply and then the client should finish, but both server and client enter an infinite loop and keep running forever. Why and how to fix that? I'm using Python 3.6.0 on Windows 10 x64 in an IPv4 network.
You must define a protocol, which is just the rules for how messages are exchanged and formatted, and how message boundaries are communicated. It appears you simply want the client to send some data and read the server response. You can achieve this by closing the write half of the client connection, in your case by calling sock.shutdown(socket.SHUT_WR), after the sock.sendall(...).
On the server side this is the read half of the same connection, and the servers detects this as EOF, causing socket.recv() to return a zero-length bytes object.
For more complicated protocols for which you want to send multiple messages on the same connection, a different strategy must be used. One simple example for a binary protocol would be to send 4 bytes representing the length in bytes of the message, then send that many bytes for the subsequent message itself.
One way is to set a timeout for the socket so it doesn't block forever when waiting for reply using socket.settimeout() as the following:
sock = socket.socket()
sock.connect(server_address)
sock.sendall('Lorem Ipsum'.encode())
sock.settimeout(5.0) # sets timeout to 5 seconds
while True:
data = sock.recv(buffer_size)
if not data:
break
print(data.decode())
sock.close()
I'm learning socket programming in python,
Server Code:
import socket
srvsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
srvsock.bind(('', 23000))
srvsock.listen(5)
while True:
clisock, (rem_host, rem_port) = srvsock.accept()
print "conection established with host %s and port %s" % (rem_host, rem_port)
while True:
strg = clisock.recv(20)
if not strg:
print 'conection closed'
clisock.close()
break
clisock.send(strg)
Client Code:
import socket
clisock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clisock.connect(('', 23000))
clisock.send("Hello World rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr dsadsadsa tttttt\n")
while True:
data = clisock.recv(20)
print type(data)
if not data:
clisock.close()
break
print data
I'm sending data stream from client to server and at the same time receiving data from server, after successful data transmission, the server not closing client connection. Did I miss any thing ?
The issue is caused because the server keeps reading data from the client until it reads no data. This only happens when the connected client closes its connection. Until then, the server socket will block (i.e. temporarily suspend operations) until the client sends more data.
Bottom line: either the client or the server has to indicate that it no longer intends to send data over the connection.
You can fix the client by adding the line
clisock.shutdown(socket.SHUT_WR)
before the for loop in the client. This indicates that no more data will be sent.
server code:
while True:
clisock, (rem_host, rem_port) = srvsock.accept()
print "conection established with host %s and port %s" % (rem_host, rem_port)
while True:
strg = clisock.recv(20)
print '[message from client:] %s'%strg
clisock.send(strg)
print 'about to close with client'
clisock.close()
print 'connection closed with client'
break
client code :
clisock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clisock.connect(('', 23000))
clisock.send("Hello World rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr dsadsadsa tttttt\n")
while True:
data = clisock.recv(20)
print '[Message from server :]%s'%data
print 'about to close server connection'
clisock.close()
print 'server connection closed'
break
This will work out in your case, holdenweb has proper a proper answer why your code is not behaving as expected in above code client only sends one message and closes the connection as well as server listens only for one message per client and closes connection to that client single client -- single connection ---- single message
I am testing a Python web server. It works as expected using localhost as the server and client, but when I test on different computers, I am getting
[Errno 54] Connection reset by peer about 20% - 80% of the time, depending on how many client threads I spawn at once. Why?
Code Snippets
Server listens:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((self.interface, self.port))
sock.listen(5)
Server loops forever, accepts client connection, spawns new thread:
while True:
(clientsock, (ip, port)) = self.sock.accept()
newthread = ClientThread(ip, port, clientsock)
newthread.start()
Spawn a bunch of client threads which connect with server, send message which requests a file, and then closes connection
Server sends message to client when ready
self.socket.sendall(message.encode())
After message is sent, close the write end of connection:
self.socket.shutdown(socket.SHUT_WR)
Client receives message (error occurs here)
def receive(self):
data_string = ''
bytes = self.sock.recv(self.bufsize)
while len(bytes) > 0:
bytes_str = bytes.decode('UTF-8')
data_string += bytes_str
bytes = self.sock.recv(self.bufsize)
return data_string
After client thread has received message, close the connection:
self.socket.close()
Receive function had errors. Changed to this:
def receive(self):
data_string = ''
while True:
bytes = self.sock.recv(self.bufsize)
bytes_str = bytes.decode('UTF-8')
data_string += bytes_str
if not bytes:
break
return data_string
Old receive function would try to call recv a second time when server had already closed socket. New one only calls once.
Also did not know you could increase listening socket backlog > 5 since Python docs say generally 5 is max, when on OS X it is 128. Increasing backlog to 128 helped.
My objective is every time the client send the data to the server, the server will display it. But Currently when the client send the data, the server capture the data and display it only for the first time. What is causing the problem? Btw, this is my first time doing network programming, so pls keep your answer simple.
Server Script
import socket
server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server_socket.bine(("",5001))
server_socket.listen(5)
print "TCP Server Waiting for incoming client connection on port 5001..."
while True:
client_socket, address =server_socket.accept()
print "Connection from ", address
data = client_socket.recv(512)
print "RECIEVED:" , data
Client Script
import socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('169.254.0.1', 5001))
data=''
while data!='quit':
data = raw_input ( "SEND :" )
client_socket.send(data)
Your server code receive only once, then accept another client.
You should loop until client disconnect. (when disconnected, recv() return empty string)
while True:
client_socket, address = server_socket.accept()
print "Connection from ", address
while 1:
data = client_socket.recv(512)
if not data:
break
print "RECIEVED:" , data
BTW, your server code (and my code) does handle only one client at a time.
while True:
client_socket, address =server_socket.accept()
print "Connection from ", address
data = client_socket.recv(512)
print "RECIEVED:" , data
This should be:
client_socket, address =server_socket.accept()
print "Connection from ", address
while True:
data = client_socket.recv(512)
print "RECIEVED:" , data
server_socket.accept() will wait indefinitely until a new client is connected. Actually your loop is like : "accept a client and receive one time the data he sent".