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.
Related
I'm trying to create a peer to peer message app, I understand I need each instance of the app to be both a server and a client as I've got for the below code but I'm wondering how to set up the ports, can I send and receive messages on the same port?
The below code is one instance of the app, I can communicate with another version but I have to set the other version to send messages on port 9000 and receive messages on 6190. This won't work going forward as how would a third user connect?
Current situation:
User 1: Receives on 9000, sends on 6190
User 2: Receives on 6190, sends on 9000
import socket
import time
import threading
global incoming
def server_socket(): #call server_socket() in build method?
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 9000))
s.listen(1)
host_name = socket.gethostname()
ip_address = socket.gethostbyname(host_name)
print("IP address is: ", ip_address)
except socket.error as e:
print("Socket Error !!", "Unable To Setup Local Socket. Port In Use")
while True:
conn, addr = s.accept()
incoming_ip = str(addr[0])
data = conn.recv(4096)
data = data.decode('utf-8')
print("message recieved is: ", data)
conn.close()
s.close()
def client_send_message():
message = "Hello World"
message = message.encode('utf-8')
c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
c.connect(("127.0.0.1", 6190))
except Exception as e:
print("Connection Refused", "The Address You Are Trying To Reach Is Currently Unavailable")
try:
c.send(message)
except Exception as e:
print(e)
c.close()
t = threading.Thread(target=server_socket)
t.start()
for i in range(5):
time.sleep(30)
client_send_message()
You currently use TCP and with this design you need a separat socket for each client. You can exchange data on this socket in both directions though. More common for peer to peer networks is UDP: here you can use a single socket to recvfrom data from arbitrary clients and sendto data to arbitrary clients.
This is probably very simple, but I am having trouble with it.
This is code I am using for the server.
I've searched for this but I only found different kinds of sockets to the one I am using.
server = socket.socket()
server.bind(("localhost", 6969))
server.listen(1)
socket_client, datos_client = server.accept()
print ("Wainting message...")
data = socket_client.recv(1000)
print ("Message:", data)
send1 = bytes("Bye","utf-8")
socket_client.send(send1)
print ("Closing..." )
socket_client.close()
server.close()
And this is the code for the client:
import socket
def main():
my_socket_client = socket.socket()
my_socket_client.connect(("localhost", 6969))
bufsize = 1000
print("Send message")
message=input()
data2 = bytes(mensaje,"utf-8")
#enviar los datos
my_socket_client.send(data2)
data_received= my_socket_client.recv(bufsize)
print (data_received)
I am not sure what your problem is since you didn't ask a question so i will just show you a client + basic command server that i have built in the same way you built yours you said "I only found different kinds of sockets to the one I am using." so i hope this is what you are looking for
Here is an example of a simple command server:
if you run the server code and then run the client you will be able to type in the client and send to the server. if you type TIME you will get from the server a respons which contains a string that has the date of today and the other commands work in the same way. if you type EXIT it will close the connection and will send from the server the string closing to the client
server:
import socket
import random
from datetime import date
server_socket = socket.socket() # new socket object
server_socket.bind(('0.0.0.0', 8820)) # empty bind (will connect to a real ip later)
server_socket.listen(1) # see if any client is trying to connect
(client_socket, client_address) = server_socket.accept() # accept the connection
while True: # main server loop
client_cmd = client_socket.recv(1024) # recive user input from client
# check waht command was entered
if client_cmd == "TIME":
client_socket.send(str(date.today())) # send the date
elif client_cmd == "NAME":
client_socket.send("best server ever") # send this text
elif client_cmd == "RAND":
client_socket.send(str(random.randrange(1,11,1))) # send this randomly generated number
elif client_cmd == "EXIT":
client_socket.send("closing")
client_socket.close() # close the connection with the client
server_socket.close() # close the server
break
else :
client_socket.send("there was an error in the commend sent")
client_socket.close() # just in case try to close again
server_socket.close() # just in case try to close again
client:
import socket
client_socket = socket.socket() # new socket object
client_socket.connect(('127.0.0.1', 8820)) # connect to the server on port 8820, the ip '127.0.0.1' is special because it will always refer to your own computer
while True:
try:
print "please enter a commend"
print "TIME - request the current time"
print "NAME - request the name of the server"
print "RAND - request a random number"
print "EXIT - request to disconnect the sockets"
cmd = raw_input("please enter your name") # user input
client_socket.send(cmd) # send the string to the server
data = client_socket.recv(1024) # recive server output
print "the server sent: " + data # print that data from the server
print
if data == "closing":
break
except:
print "closing server"
break
client_socket.close() # close the connection with the server
you have a typo .
edit this line in client from
data2 = bytes(mensaje,"utf-8")
to
data2 = bytes(message,"utf-8")
I tried your code, and made a couple of changes:
Server side:
import socket
server = socket.socket()
server.bind(("localhost", 6969))
server.listen(1)
socket_client, datos_client = server.accept()
print ("Waiting message...")
data = socket_client.recv(1000)
print ("Message:", data )
# Same change made as with client side
send1 = bytes("Bye") #,"utf-8")
socket_client.send(send1)
print ("Closing..." )
socket_client.close()
server.close()
Client side:
import socket
my_socket_client = socket.socket()
my_socket_client.connect(("localhost", 6969))
bufsize = 1000
print("Send message")
# I changed it to raw_input(); input() does not for string input with python 2.7
message=raw_input()
# Are you trying to encode the message? To make it simple, skip it
data2 = bytes(message) # ,"utf-8")
#enviar los datos
my_socket_client.send(data2)
data_received= my_socket_client.recv(bufsize)
print (data_received)
Sample output from server side:
Waiting message...
('Message:', 'message from client')
Closing...
Sample output from client side:
Send message
message from client
Bye
This may have been already answered but did not find anything or dont know what to search for. I have a socket server threaded for multiple clients (code below) and want the server to run code (ie. check the status of something) and then send a message to the clients. How do I go about doing this?
To clarify, I need to learn how to add a asynchronous task to this code so it can do checking and send a message to the clients if it needs to
Example: while there are clients connected I want the server to continually check a log file and if it changes and if so I want it to send a message to the clients
Server.py(working code)
from socket import *
import thread
BUFF = 1024
HOST = '127.0.0.1'# must be input parameter #TODO
PORT = 9999 # must be input parameter #TODO
def response(key):
return 'Server response: ' + key
def handler(clientsock,addr):
while 1:
data = clientsock.recv(BUFF)
if not data: break
print repr(addr) + ' recv:' + repr(data)
clientsock.send(response(data))
print repr(addr) + ' sent:' + repr(response(data))
if "close" == data.rstrip(): break # type 'close' on client console to close connection from the server side
clientsock.close()
print addr, "- closed connection" #log on console
if __name__=='__main__':
ADDR = (HOST, PORT)
serversock = socket(AF_INET, SOCK_STREAM)
serversock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
serversock.bind(ADDR)
serversock.listen(5)
while 1:
print 'waiting for connection... listening on port', PORT
clientsock, addr = serversock.accept()
print '...connected from:', addr
thread.start_new_thread(handler, (clientsock, addr))
I have added below code server.py and this works for sending a status change message when log file changes.
import socket
import sys
import time
from thread import *
HOST = 'localhost' # Symbolic name meaning all available interfaces
PORT = 9999 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Socket created'
#Bind socket to local host and port
try:
s.bind((HOST, PORT))
except socket.error as msg:
print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
sys.exit()
print 'Socket bind complete'
#Start listening on socket
s.listen(10)
print 'Socket now listening'
#Function for handling connections. This will be used to create threads
def clientthread(conn):
#Sending message to connected client
conn.send('Welcome to the server. Type something and hit enter\n') #send only takes string
data = conn.recv(1024)
#infinite loop so that function do not terminate and thread do not end.
while True:
logfile = open("serverlog.txt","r")
#Receiving from client
logfile.seek(0,2)
while True:
line = logfile.readline()
if not line:
time.sleep(0.1) # Sleep briefly
continue
reply = 'File Changed...Your Data' + data
break
conn.sendall(reply)
#came out of loop
conn.close()
#now keep talking with the client
while 1:
#wait to accept a connection - blocking call
conn, addr = s.accept()
print 'Connected with ' + addr[0] + ':' + str(addr[1])
#start new thread takes 1st argument as a function name to be run, second is the tuple of arguments to the function.
start_new_thread(clientthread ,(conn,))
s.close()
To test it run this server.py in one command prompt and keep it open. something like this
> python server.py
Socket created
Socket bind complete
Socket now listening
And run a simple telnet from other cmd prompt to verify the connection
telnet localhost 9999
Replace localhost with IP. Type anything on these telnet connection and you should get response properly.
Also you can check on server.py cmd prompt for the connections made.
And as I mentioned, check this link.
I have two scripts, Server.py and Client.py.
I have two objectives in mind:
To be able to send data again and again to server from client.
To be able to send data from Server to client.
here is my Server.py :
import socket
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = "192.168.1.3"
port = 8000
print (host)
print (port)
serversocket.bind((host, port))
serversocket.listen(5)
print ('server started and listening')
while 1:
(clientsocket, address) = serversocket.accept()
print ("connection found!")
data = clientsocket.recv(1024).decode()
print (data)
r='REceieve'
clientsocket.send(r.encode())
and here is my client :
#! /usr/bin/python3
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host ="192.168.1.3"
port =8000
s.connect((host,port))
def ts(str):
s.send('e'.encode())
data = ''
data = s.recv(1024).decode()
print (data)
while 2:
r = input('enter')
ts(s)
s.close ()
The function works for the first time ('e' goes to the server and I get return message back), but how do I make it happen over and over again (something like a chat application) ?
The problem starts after the first time. The messages don't go after the first time.
what am I doing wrong?
I am new with python, so please be a little elaborate, and if you can, please give the source code of the whole thing.
import socket
from threading import *
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = "192.168.1.3"
port = 8000
print (host)
print (port)
serversocket.bind((host, port))
class client(Thread):
def __init__(self, socket, address):
Thread.__init__(self)
self.sock = socket
self.addr = address
self.start()
def run(self):
while 1:
print('Client sent:', self.sock.recv(1024).decode())
self.sock.send(b'Oi you sent something to me')
serversocket.listen(5)
print ('server started and listening')
while 1:
clientsocket, address = serversocket.accept()
client(clientsocket, address)
This is a very VERY simple design for how you could solve it.
First of all, you need to either accept the client (server side) before going into your while 1 loop because in every loop you accept a new client, or you do as i describe, you toss the client into a separate thread which you handle on his own from now on.
client.py
import socket
s = socket.socket()
s.connect(('127.0.0.1',12345))
while True:
str = raw_input("S: ")
s.send(str.encode());
if(str == "Bye" or str == "bye"):
break
print "N:",s.recv(1024).decode()
s.close()
server.py
import socket
s = socket.socket()
port = 12345
s.bind(('', port))
s.listen(5)
c, addr = s.accept()
print "Socket Up and running with a connection from",addr
while True:
rcvdData = c.recv(1024).decode()
print "S:",rcvdData
sendData = raw_input("N: ")
c.send(sendData.encode())
if(sendData == "Bye" or sendData == "bye"):
break
c.close()
This should be the code for a small prototype for the chatting app you wanted.
Run both of them in separate terminals but then just check for the ports.
This piece of code is incorrect.
while 1:
(clientsocket, address) = serversocket.accept()
print ("connection found!")
data = clientsocket.recv(1024).decode()
print (data)
r='REceieve'
clientsocket.send(r.encode())
The call on accept() on the serversocket blocks until there's a client connection. When you first connect to the server from the client, it accepts the connection and receives data. However, when it enters the loop again, it is waiting for another connection and thus blocks as there are no other clients that are trying to connect.
That's the reason the recv works correct only the first time. What you should do is find out how you can handle the communication with a client that has been accepted - maybe by creating a new Thread to handle communication with that client and continue accepting new clients in the loop, handling them in the same way.
Tip: If you want to work on creating your own chat application, you should look at a networking engine like Twisted. It will help you understand the whole concept better too.
I am learning socket programming using python. my first assignment is to a write a client.py and a server.py. The client sends a message to server. The server receives the message of 16 bytes each time. After it has received the entire message, it will send the same message back to client.
so it is very simple. The server has backlog of 1. After the server sends the message to client, the connection to client close and the server should be open to receive new connection.
my current code fails in the last step. It is not open to receive new connections. It is throwing error. I even figured out the error. but I do not know how to fix this.
The error comes from server.py because I call for sock.accept() but I have closed the sock.
Let me explain my server.py code: I have two while loops. The outer loop looks for new connection, and the inner loop looks process request from connections i.e it simply receives data, wait till everything is received and send it back to client and finally close the connection.
I am asked not to change the structure of two while loops but just implement them.
Any thoughts or ideas on this:
client.py
import socket
import sys
def client(msg, log_buffer=sys.stderr):
server_address = ('localhost', 10000)
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM,socket.IPPROTO_IP)
sock.connect(server_address)
print >>log_buffer, 'connecting to {0} port {1}'.format(*server_address)
try:
print >>log_buffer, 'sending "{0}"'.format(msg)
sock.sendall(msg)
chunk = ''
done=False;
while not done:
chunk+=sock.recv(16)
if chunk==msg:
done=True
print >>log_buffer, 'received "{0}"'.format(chunk)
finally:
print >>log_buffer, 'closing socket'
sock.close()
if __name__ == '__main__':
if len(sys.argv) != 2:
usg = '\nusage: python echo_client.py "this is my message"\n'
print >>sys.stderr, usg
sys.exit(1)
msg = sys.argv[1]
client(msg)
Server.py
import socket
import sys
def server(log_buffer=sys.stderr):
# set an address for our server
address = ('127.0.0.1', 10000)
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM,socket.IPPROTO_IP)
sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# log that we are building a server
print >>log_buffer, "making a server on {0}:{1}".format(*address)
sock.bind(address)
sock.listen(1)
try:
# the outer loop controls the creation of new connection sockets. The
# server will handle each incoming connection one at a time.
while True:
print >>log_buffer, 'waiting for a connection'
conn,add=sock.accept()
addr=(conn,add)
try:
print >>log_buffer, 'connection - {0}:{1}'.format(*addr)
# the inner loop will receive messages sent by the client in
# buffers. When a complete message has been received, the
# loop will exit
data = ''
while True:
recvdata=conn.recv(16)
print recvdata
data+=recvdata
print >>log_buffer, 'received "{0}"'.format(data)
print >>log_buffer, "len of received data: {0}".format(len(recvdata))
if len(recvdata)<16:
print >>log_buffer,"sending data"
conn.sendall(data)
break
conn.close()
finally:
sock.close()
except KeyboardInterrupt:
sock.close()
if __name__ == '__main__':
server()
sys.exit(0)
I runpython server.py in one terminal andpython client.py "This is the first message. send me back"` in a different terminal. The client connection is lost normally as expected. But I get the following error at server side (towards the end):
making a server on 127.0.0.1:10000
waiting for a connection
connection - <socket._socketobject object at 0x100849c20>:('127.0.0.1', 50626)
sairam hopefully
received "sairam hopefully"
len of received data: 16
this works lets
received "sairam hopefully this works lets"
len of received data: 16
c
received "sairam hopefully this works lets c"
len of received data: 2
sending data
waiting for a connection
Traceback (most recent call last):
File "echo_server.py", line 89, in <module>
server()
File "echo_server.py", line 39, in server
conn,add=sock.accept()
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 202, in accept
sock, addr = self._sock.accept()
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 170, in _dummy
raise error(EBADF, 'Bad file descriptor')
socket.error: [Errno 9] Bad file descriptor
You are closing sock inside your while loop. Don't do that. sock is your long-lasting server socket, which needs to remain open to listen for new connections. conn is your ephemeral socket, which needs to remain open only the length of a single connection.
Close conn after each connection, close sock when the server needs to terminate.
More simply, replace these lines:
finally:
sock.close()
with
finally:
conn.close()
What you are trying to do is a simple echo server, which I believe you can implement much more simply.
Server:
import socket
host = ''
port = 50000
backlog = 5
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(backlog)
while 1:
client, address = s.accept()
data = client.recv(size)
if data:
client.send(data)
client.close()
Client:
import socket
host = 'localhost'
port = 50000
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
s.send('Hello, world')
data = s.recv(size)
s.close()
print 'Received:', data