I have created a client server setup from a tutorial, but the server is stuck in the while loop below and i can't figure out why.
I have searched through the questions on here and as far as I can see it should work.
I'm sure it will be something simple. I'm new to Python so any help would be appreciated.
Please know this is my first question so i hope it works ok.
I'm using python 3.5.2
# create a client thread
def clientthread(conn):
# sending message to the client
message = 'Welcome to the Server. Type something and hit Enter\n'
conn.send(message.encode()) # send only takes a string
while 1:
# receiving from client
data = conn.recv(1024)
if not data.decode(): break
reply = 'OK ' + data.decode()
conn.sendall(reply.encode())
# came out of loop
conn.close()
# keep server up
while 1:
# accept incomming connections
conn, addr = soc.accept()
# display client info
print('Connected with' + addr[0] + ':' + str(addr[1]))
# start a new thread takes function name and a tupal
start_new_thread(clientthread, (conn, ))
soc.close()
Figured out the issue, I was using telnet to test the server and it adds a \r\n to the end which the server see's as data so never shuts down. Added code to check for this and works fine now
Related
I have the following code for my server loop:
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind((host, port))
while True:
server.listen(1)
clientsock, clientAddress = server.accept()
self.total_clients += 1
self.modules['logger'].log("login", "New connection! => " + str(clientAddress))
self.clients[self.total_clients] = (Client(clientAddress, clientsock, self.total_clients, self.modules))
self.clients[self.total_clients].start()
Basically someone connects to the socket, and after that they're placed in that loop on the 2nd to last line (the one which instantiates the Client class). The Client class is as follows:
class Client(threading.Thread):
def __init__(self, addr, clientsocket, thread_id, modules):
threading.Thread.__init__(self)
self.csocket = clientsocket
self.addr = addr
self.thread_id = thread_id
self.modules = modules
return
def run(self):
while True:
data = self.csocket.recv(2048)
if(len(data) > 1):
data = data.decode()
if data == 'bye':
break
self.clientLog("Data received: {" + data + "}")
self.parseCatch(self.modules['parser'].parse(data))
print ("Client ", clientAddress , " disconnected...")
So basically I want the program to work like this: A client connects to the socket. They are then placed into the run() loop in the Client class-thread indefinitely for anything else they send, and the loop responds to certain packets (this is done in the parseCatch() function which I have not included as it is just a simple "if x received send y back").
Anyways, the program isn't functioning like that. As it works now, a client connects to the socket and is placed into the run() loop in the Client class-thread. This is good so far. They then send a certain packet, lets say they send "hi". This is received in 'data' in the run loop in the bottom Client class, and let's say I respond back to hi with self.csocket.send('hi back');. This works fine. Their client receives the hi back. However, if they send something back, like bye, it is treated as a brand new client.
So somehow, when this arbitrary client replies to my packet I sent in the Client() thread, they are treated as a brand new connection. So if client sends "hi", server sends "hi back", it is so far so good. However, if a client then responds again and says something like "bye", it is somehow handled by the main server loop in the top block of code, and I get the "New connection! =>" message. I do not want the client to be handled in this loop, I want them to be handled in their own preexisting thread.
For some reason when a client replies with new data they exit their thread. The loop appears to not even be broken, because it never says "Client disconnected".
Please help. Thanks.
In trying to familiarize myself with the socket library, I have a simple server and client setup. Basically I've stumbled through and am able to set up connection and get the server and client to talk to each other. To make it more interactive, I have client.py able to send text through the command line. Everything appears to be working properly (with the exception of the server side tearing down connection properly if client input is blank), if I type a message from the client side, it spits it right back out to me. In this example, I have it set up for the server side to print the text as well. What I noticed was, that the server side doesn't alway 'register' what it being sent from the client. I am trying to figure out why this is the case. For being a test, it doesn't really affect anything, I just can't figure out what is taking place behind the scenes.
EDIT:
Actually, after playing around with it for a bit, it appears every other message is being printed out to the server console. I've still yet to figure out why this is the case
Server side:
#server.py
import socket
ss = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ss.bind(('127.0.0.1',5000))
ss.listen(5)
while True:
conn, addr = ss.accept()
with conn:
print ('Connected by', addr)
while True:
data = conn.recv(4096)
print (data)
if not data:
print ("nothing received from client")
ss.close()
break
Client side:
#client.py
import socket
server = 'localhost'
port = 5000
s = socket. socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 5000))
s.send(bytes(b'Client has connected'))
while True:
msg = input()
s.send(bytes(input(msg),'utf-8'))
if not msg:
print ("Server should tear down connection...")
# s.close()
break
In sockets you there are no methods __exit__ implemented, so you can't use the with conn:
you need to remove this part of code.
I have been self-learning python since few months now , and finally learning Socket programming. As an text book exercise, I am supposed to design a half-duplex chat system . Below is the code. The first request and response are just fine , but everytime I try sending a second message from client, the server seems to be hanging. The program is TCP based.
I am suspecting that since ss.accept() is being called everytime a new message has to be sent, a new thread is being created but since I have made only 1 call to sc.connect() from client , may be my new connection at the server end is hanging there for infinite time.
As a trail : I called ss.accept() outside the while loop, ie making only 1 connection and listening to data over and over on while loop, the conversations works just fine
Can someone please have a look a the code and help me understand where exactly is the issue.
Since, I am learning, I have not moved to twisted yet. I want to learn all the basics first before I move to frameworks.
!bin/usr/env python
import socket, sys
HOST =''
PORT = 1060
ADDR =(HOST,PORT)
def userinput(sock):
usermessage = input('>')
sock.sendall(str(len(usermessage)))
return usermessage
def server():
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
s.bind(ADDR)
s.listen(1)
print 'the server is listening at',s.getsockname()
while True:
ss,sockname = s.accept()
#listen to determine the bytes sent by client
msglen = ss.recv(4096)
#accept the complete message
msg = ss.recv(int(msglen))
print 'client:', repr(msg)
servermsg = userinput(ss)
ss.sendall(servermsg)
print " ---------------"
ss.close()
def client():
sc = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sc.connect(ADDR)
while True:
message = userinput(sc)
sc.sendall(message)
replylen = sc.recv(4096)
reply = sc.recv(int(replylen))
print "reply:",reply
print "----------------"
sc.close()
if sys.argv[1:] == ['server']:
server()
elif sys.argv[1:] == ['client']:
client()
else:
print >> sys.stderr,'usage:tcp_2_7.py server|client[host]'
Your trial - accepting once and then receiving multiple messages - is how you should do this. Calling accept is waiting for a new connection - you don't need to do this every time you want to send or receive a message, just as you don't want to call connect every time you want to send or receive.
Think of it this way:
When you connect to a chat server, do you connect, send a message, then disconnect immediately? No - you have a constant open connection which messages are sent through, and the connection is only closed at the end of a chat session.
From the docs on accept:
socket.accept()
Accept a connection. The socket must be bound to an
address and listening for connections. The return value is a pair
(conn, address) where conn is a new socket object usable to send and
receive data on the connection, and address is the address bound to
the socket on the other end of the connection.
Recently, I managed to create sockets on my PC and my Raspberry Pi to enable communication between both devices. Currently, the client is able to automatically send messages to the server. I was wondering, if it is possible to modify the scripts to send tcp data packets instead of purely text messages, as I would very much like to control the raspberry pi using my PC in the future without having the need to ssh/etc.
I've looked at some examples, but as I don't have much experience in writing my own scripts/codes, I'm not very sure how to go about doing this. I would appreciate if someone could guide me in the right direction with explanation and some examples if possible.
Anyway here is the server/client script I'm running at the moment:
Client:
import socket
import sys
import struct
import time
#main function
if __name__ == "__main__":
if(len(sys.argv) < 2) :
print 'Usage : python client.py hostname'
sys.exit()
host = sys.argv[1]
port = 8888
#create an INET, STREAMing socket
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error:
print 'Failed to create socket'
sys.exit()
print 'Socket Created'
try:
remote_ip = socket.gethostbyname( host )
s.connect((host, port))
except socket.gaierror:
print 'Hostname could not be resolved. Exiting'
sys.exit()
print 'Socket Connected to ' + host + ' on ip ' + remote_ip
#Send some data to remote server
message = "Test"
try :
#Set the whole string
while True:
s.send(message)
print 'Message sent successfully'
time.sleep(1)
print 'Sending...'
except socket.error:
#Send failed
print 'Send failed'
sys.exit()
def recv_timeout(the_socket,timeout=2):
#make socket non blocking
the_socket.setblocking(0)
#total data partwise in an array
total_data=[];
data='';
#beginning time
begin=time.time()
while 1:
#if you got some data, then break after timeout
if total_data and time.time()-begin > timeout:
break
#if you got no data at all, wait a little longer, twice the timeout
elif time.time()-begin > timeout*2:
break
#recv something
try:
data = the_socket.recv(8192)
if data:
total_data.append(data)
#change the beginning time for measurement
begin=time.time()
else:
#sleep for sometime to indicate a gap
time.sleep(0.1)
except:
pass
#join all parts to make final string
return ''.join(total_data)
#get reply and print
print recv_timeout(s)
s.close()
Server:
import socket
import sys
from thread import *
HOST = '' # Symbolic name meaning all available interfaces
PORT = 8888
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Socket created'
try:
s.bind((HOST, PORT))
except socket.error , msg:
print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
sys.exit()
print 'Socket bind complete'
s.listen(10)
print 'Socket now listening'
#Function for handling connections
def clientthread(conn):
#Sending message to connected client
conn.send('Welcome to the server. Receving Data...\n') #send only takes string
#infinite loop so that function do not terminate and thread do not end.
while True:
#Receiving from client
data = conn.recv(1024)
reply = 'Message Received at the server!\n'
print data
if not data:
break
conn.sendall(reply)
conn.close()
#now keep talking with the client
while 1:
#wait to accept a connection
conn, addr = s.accept()
print 'Connected with ' + addr[0] + ':' + str(addr[1])
#start new thread
start_new_thread(clientthread ,(conn,))
s.close()
socket.socket(socket.AF_INET, socket.SOCK_STREAM) already creates a connection that provides a reliable stream of bytes between two machines. This uses TCP, which is on top of IP and Ethernet. The latter two are package-based, while TCP creates a stream of continuous bytes on top of it. It also adds some error checking and error correction, so it is pretty reliable.
I honestly don't understand what you want to achieve with what you call "send packets". What you don't want to do is to create an implementation of TCP yourself, as that's a non-trivial task, so sending RAW packets is out. In general, even using TCP is already relatively low-level and should be avoided unless really necessary.
Using e.g. ZeroMQ you get a message-based interface that does all the transmission for you. It does so on top of TCP (or other transports) and adds more error correction for e.g. disconnects. There, you also have something like "packets", but those are independent of how many TCP or IP packets were required to send it underneath. If you don't want to implement a specific protocol, I'd suggest you use this framework instead of lowlevel TCP sockets.
Another simple alternative is to use HTTP, for which there is also existing code in Python. The downside is that it is always one side that initiates some communication and the other side only replies. If you want some kind of active notification, you either have to poll or use hacks like delaying an answer.
You are already sending data packets - those packets juts happen to contain text data at the moment. Try looking into pickle in the standard libraries and into pyro.
I am currently coding my first basic socket server, and I have stumbled upon two different forms for the server to communicate with the client - threads (which I think use conn in python) and channels, which I don't really understand - but they seem like another way to communicate between the client and server. What is the difference between the two and how are they best used?
Here is the code as asked for - please pardon my N00biness:)
CONN/THREADS
def clientthread(conn):
#Sending message to connected client
#This only takes strings (words)
conn.send("Welcome to the server. Type something and hit enter\n")
#loop so that function does not terminate and the thread does not end
while True:
#Receiving from client
data = conn.recv(1024)
if not data:
break
conn.sendall(data)
print data
#To close the connection
conn.close()
while True:
#Wait to accept a connection - blocking call
conn, addr = s.accept()
#display client information (IP address)
print 'Connected with ' + addr[0] + ':' + str(addr[1])
#Start new thread takees 1st argument as a function name to be run, second
#is the tuple of arguments to the function
start_new_thread(clientthread ,(conn,))
CHANNELS
while True:
#Wait to accept a connection - blocking call
channel, details = s.accept()
#display client information (IP address)
print 'Connected with ', details
#Start new thread takees 1st argument as a function name to be run, second
#is the tuple of arguments to the function
#Sending message to connected client
#This only takes strings (words)
intro = "Welcome to the server. Type something and hit enter"
print channel.recv(len(intro))
channel.send(intro)
#loop so that function does not terminate and the thread does not end
while True:
#Receiving from client
data = channel.recv(1024)
if not data:
break
channel.sendall(data)
print data
They do exactly the same thing, except one uses channel and the other uses conn.