Server/Client continuous connection in python? (Python 3x) - python

Hi everyone this is my firs post here and I have a question about python server/client continuous connection where I can write as a client and comes back to the server, and it shouldn't stop till i type "end".
This is my server:
from socket import *
def main():
s=socket(AF_INET, SOCK_STREAM)
s.bind((' ', 10530))
s.listen(1)
conn, (rmip, rmpt) = s.accept()
while 1:
print ("Connected by ", str(rmip)+": " +str(rmpt))
data = conn.recv(1024)
print ("What was delivered: ", data.decode())
if not data:
break
conn.close()
main()
This si my client:
from socket import *
def main():
s = socket(AF_INET, SOCK_STREAM)
s.connect(('localhost',10530))
sendme = input("What do you want to send\n")
s.send(sendme.encode())
main()
Now all I want is this connection to continue so I can write something else again and again client-server, until the client ends the connection, Like shown in the picture here
Thank you very much for help! :)

You have a while loop in your server which keeps going until an empty payload is received. You don't have any looping construct in your client, however, so it will exit after one message.
Add a loop to your client as well, and check for an input of end, at which point you can break out of the loop.

Related

error 10054 in a multithreaded server program in python

I am trying to design a multithreaded server. client1 send data to server and server forwards data to client2 for processing. client2 sends processed data to server and then server forwards it to client1.
Data from client1 is received by client2 through server while execution, but my server program after sending data to client2 terminates with error
[10054] An existing connection was forcibly closed by remote host.
client1.py
from socket import *
import thread
ip='127.1.1.2'
port=5554
s=socket(AF_INET, SOCK_STREAM)
s.connect((ip,port))
data=raw_input("Input lowercase :: ")
while data!="#close":
s.send(data)
data=raw_input("Input next word or type #close to exit: ")
s.close()
client2.py
from socket import *
import thread
ip='127.1.1.2'
port=5554
s=socket(AF_INET, SOCK_STREAM)
s.connect((ip,port))
m=s.recv(1024)
k=m.upper()
print "Uppercase of ",m," in System--> ",k
s.close()
server.py
from socket import *
import thread
ip='127.1.1.2'
port=5554
data=''
def multi_threading(c,a):
while True:
global data
print "Inside client 1 thread"
data= c.recv(1024)
if not data:
break
if "close"==data.rstrip():
break
c.close()
print a,"--terminates connection"
def multi_threading2(c,a):
while True:
print "Inside client 2 thread"
c.send(data)
if not data:
break
if "close"==data.rstrip():
break
c.close()
print a,"--terminates connection"
if __name__=='__main__':
s=socket(AF_INET, SOCK_STREAM)
s.setsockopt(SOL_SOCKET, SO_REUSEADDR,1)
s.bind((ip,port))
s.listen(4)
count=0
while True:
print "Server is listening on port number ",port
c,a=s.accept()
count=count+1
print "--------------------------------------------------"
print "Server connected to system having ip address --> ",a
if(count==1):
thread.start_new_thread(multi_threading,(c,a))
else:
thread.start_new_thread(multi_threading2,(c,a))
What i might be doing wrong?
I'm trying to help by changing your code as little as possible. It isn't how I would write it but should allow you to follow along. This is also not very idomatic Python. I just want you to see how to get the basic interaction going.
Some comments about my changes:
Remove the indent in client1.py so you don't always close the
socket with s.close(). I suspect this was a typo in your post?
In server.py it isn't safe to access the global data between two
threads. At the very least you need a semaphore to protect it.
Every time around multi_threading loop you destroy the last value of
data. You need to append the incoming bytes to a data structure
like a list. I renamed the threads to make it easier to understand.
You are expecting to see close in the server but you don't ever send this because your loop terminates when you type #close. You need to adjust for this.
Your code is order dependent because both client 'sender' and client 'receiver' use the same port. You need to put something into the protocol to distinguish between these two roles so you can start them in either order. This makes the system more robust.
Due to the sender not necessarily having any data I do a crude sleep. This can be avoided by using a shared queue between the threads which would block one end
You need some framing because you can't guarantee the speed at which the independent processes send and receive to the socket. I use \n for this.
There is an edge case if you sent very large strings (and removed the 1024 read) you could not get a full word with the \n through. I ignore this case.
I adjust the loopback address
I wrote this in PyCharm CE. I recommend using an IDE (PyCharm is excellent) with breakpoints. You can step through all the processes bit by bit. Put breakpoints in the threads and step through the actions.
Result:
server.py
from socket import *
import thread
from threading import Lock
import time
ip = '127.0.0.1'
port = 5554
data = []
data_lock = Lock()
def multi_threading_recv(sock, a):
should_run = True
while should_run:
global data
print "Inside client 1 thread"
_data = sock.recv(1024)
if _data:
with data_lock:
for word in _data.split('\n'):
data.append(word)
if "#close" == word:
should_run = False
break
else:
break
sock.close()
print a, "--terminates connection"
def multi_threading_send(sock, a):
while True:
print "Inside client 2 thread"
with data_lock:
if len(data) == 0:
time.sleep(1) # Not ideal. Ideally block on a shared queue
continue
else:
_data = data.pop(0)
if _data == "#close":
break
sock.send(_data + '\n')
c.close()
print a, "--terminates connection"
if __name__ == '__main__':
s = socket(AF_INET, SOCK_STREAM)
s.setsockopt(SOL_SOCKET, SO_REUSEADDR,1)
s.bind((ip,port))
s.listen(4)
count = 0
while True:
print "Server is listening on port number ", port
c, a = s.accept()
print "--------------------------------------------------"
print "Server connected to system having ip address --> ", a
role = c.recv(4)
if role == 'PUSH':
thread.start_new_thread(multi_threading_recv, (c, a))
elif role == 'PULL':
thread.start_new_thread(multi_threading_send, (c,a))
else:
print('invalid role: ' + role)
c.close()
client1.py
from socket import *
ip = '127.0.0.1'
port = 5554
s = socket(AF_INET, SOCK_STREAM)
s.connect((ip,port))
s.send('PUSH')
while True:
data = raw_input("Input word or type #close to exit: ")
s.send(data + '\n')
if data == "#close":
break
s.close()
client2.py
from socket import *
ip = '127.0.0.1'
port = 5554
s = socket(AF_INET, SOCK_STREAM)
s.connect((ip, port))
s.send('PULL')
while True:
data = s.recv(1024)
if data:
words = data.split('\n')
for w in words:
print(w)
else:
break
s.close()
Output:
client1
Input word or type #close to exit: hello
Input word or type #close to exit: world
Input word or type #close to exit: #close
client2:
hello
world
server:
Server is listening on port number 5554
--------------------------------------------------
Server connected to system having ip address --> ('127.0.0.1', 62605)
Server is listening on port number 5554
Inside client 1 thread
('127.0.0.1', 62605) --terminates connection
--------------------------------------------------
Server connected to system having ip address --> ('127.0.0.1', 62614)
Server is listening on port number 5554
Inside client 2 thread
Inside client 2 thread
Inside client 2 thread
('127.0.0.1', 62614) --terminates connection
There is one final comment that the server will go around the loop again and keep on accepting clients. The code doesn't cope with this and I leave it as an exercise for you. You can multiplex multiple senders and receivers if you add a channel number to the PUSH and PULL initiation of the protocol (e.g. PUSH3, PULL3). This will then allow you to store the incoming data in a dictionary keyed by this integer and then send it out to the correct client.

Python continuous TCP connection

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

Calling .recv(1024) and .send() twice, nothing happening (Python)

I am trying to learn Socket coding right now, and I wrote a little piece of Process-to-Process communication.
This is the Servercode:
import socket
s = socket.socket()
host = socket.gethostname()
port = 17752
s.bind((host, port))
s.listen(5)
while True:
(client, address) = s.accept()
print(address, 'just connected!')
message = input("Would you like to close the connection? (y/n)")
if message == 'y':
message = "False"
client.send(message.encode(encoding="utf_8"))
client.close()
break
elif message == 'n':
print("sending message...")
testing = "Do you want to close the connection?"
client.send(testing.encode(encoding='utf_8'))
print("sent!")
And the Clientcode:
import socket
client = socket.socket()
host = socket.gethostname()
port = 17752
client.connect((host, port))
while True:
print("awaiting closing message...")
closing = client.recv(1024)
closing = closing.decode(encoding='utf_8')
print("Closing message recieved and decoded")
if closing == 'False':
print("message is false, breaking loop")
break
else:
print("Awaiting message...")
recieved = client.recv(1024)
recieved = recieved.decode(encoding='utf_8')
print("Message recieved and decoded")
print(recieved)
sd = input('(y/n) >')
if sd == 'y':
print("Closing connection")
client.close()
break
print("Sorry, the server closed the connection!")
What it is meant to do?
It is basically to learn and practice socket coding.
It should be a program that sends data from the Server to the Client with both being able to terminate the connection by answering y or n to the questions.
If both sides keep answering n the program just keeps running.
As soon as someone answers y it terminates either the Server or the client.
Now, I don't know what to heck is wrong there.
If I type 'y' for the Servers question "Would you like to close this connection?" it all works as it should.
If I type 'n' the Server does what it should, but the client does not recieve anything. Most of the 'print' statements are for debugging. Thats how I know the Server works fine.
What is wrong there? I tried to find it, I couldn't.
I am kinda new to python and new to socket coding. So keep it easy please.
Thanks.
(I run it with Batch scripts under Win10 cmd)
(Since it is Process-to-Process it is probably not called a "Server"?)
In you code each connect should have a matching accept on server side.
Your client connects once per session,
but the server accepts after each message, so at the point where the second recv is invoked the server is already trying to accept another client.
Apparently your server is supposed to handle only one client,
so you can just move the call to accept out of the loop:
s.listen(5)
(client, address) = s.accept()
print(address, 'just connected!')
while True:
message = raw_input("Would you like to close the connection? (y/n)")

s.sendall doesn't work inside a thread in python

I'm trying to develop a chat program in python. I want it to have multiple clients so I'm using threading to handle this. However when I try to send the message to all connected clients, the server only sends it to the client which sent the message. I'm not sure if I'm just missing something obvious but here is the code for the server:
import socket
from thread import *
host = '192.168.0.13'
port = 1024
users = int(input("enter number of users: "))
def clienthandler(conn):
while True:
data = conn.recv(1024)
if not data:
break
print data
conn.sendall(data)
conn.close()
serversock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversock.bind((host, port))
serversock.listen(users)
for i in range(users):
conn, addr= serversock.accept()
print 'Connected by', addr
start_new_thread(clienthandler, (conn,))
And here is the code for the client:
import socket
host = '192.168.0.13'
port = 1024
usrname = raw_input("enter a username: ")
usrname = usrname + ": "
clientsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientsock.connect((host, port))
while True:
x = raw_input('You: ')
x = usrname + x
clientsock.sendall(x)
data = clientsock.recv(1024)
print data
The "all" in sendall means that it sends all of the data you asked it to send. It doesn't mean it sends it on more than one connection. Such an interface would be totally impractical. For example, what would happen if another thread was in the middle of sending something else on one of the connections? What would happen if one of the connections had a full queue?
sendall: Send data to the socket. The socket must be connected to a remote socket. The optional flags argument has the same meaning as for recv() above. Unlike send(), this method continues to send data from string until either all data has been sent or an error occurs. None is returned on success. On error, an exception is raised, and there is no way to determine how much data, if any, was successfully sent. -- 17.2. socket
You can try by pulling up the list of users, and iterating through it, and doing an individual send of the same message, though, unless you are the administrator and want to broadcast a warning, this functionality would be pretty mundane.

Sending string via socket (python)

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.

Categories