Basic python socket server application doesnt result in expected output - python

Im trying to write a basic server / client application in python, where the clients sends the numbers 1-15 to the server, and the server prints it on the server side console.
Code for client:
import socket
clientsocket.connect(('localhost', 8303))
def updateX():
x = 0
while (x < 15):
x
clientsocket.send(format(x))
print x
x = x+1
updateX()
server:
import socket
HOST = 'localhost'
PORT = 8303
s= socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(5) # become a server socket, maximum 5 connections
connection, address = s.accept()
while True:
connection, address = s.accept()
buf = connection.recv(64)
print buf
The output of running the client while the server is live results in either no output, prints only 1, or prints only 12. Ideas?

Before entering the main loop on the server side, you accept a connection:
connection, address = s.accept()
But then in the loop itself you begin by accepting a connection:
while True:
connection, address = s.accept()
buf = connection.recv(64)
print buf
As a result, you never read from the first connection. That's why you don't see any output.
Note also that it's wrong (for what you're trying to do) to accept a new connection on every iteration. Even if you keep making new client connections, the server will accept a connection on each iteration and read from the socket once, but then continue the next iteration and wait for a new connection, never reading more data sent by a client. You should be making multiple recv calls on the same connection object instead.
You might find this tutorial helpful.

There are multiple errors:
socket.send() might send only partial content, use socket.sendall() instead
format(12) returns '12' therefore even if your code sends all numbers and the server correctly receives them then it sees '01234567891011121314' i.e., individual numbers are not separated
double socket.accept() mentioned by #Alp leads to ignoring the very first connection
socket.recv(64) may return less than 64 bytes, you need a loop until it returns an empty bytestring (meaning EOF) or use socket.makefile()
Client:
#!/usr/bin/env python
"""Send numbers in the range 0..14 inclusive as bytes e.g., 10 -> b'\n'
Usage: python client.py [port]
"""
import sys
import socket
from contextlib import closing
port = 8686 if len(sys.argv) < 2 else int(sys.argv[1])
with closing(socket.create_connection(('localhost', port))) as sock:
sock.sendall(bytearray(range(15))) # send each number as a byte
sock.shutdown(socket.SHUT_RDWR) # no more sends/receives
You need to know how numbers are separated in the data. In this case, a fixed format is used: each number is a separate byte. It is limited to numbers that are less than 256.
And the corresponding server:
#!/usr/bin/env python
"""
Usage: python server.py [port]
"""
from __future__ import print_function
import sys
import socket
from contextlib import closing
host = 'localhost'
port = 8686 if len(sys.argv) < 2 else int(sys.argv[1])
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # ipv4 version
try:
s.bind((host, port))
s.listen(5)
print("listening TCP on {host} port {port}".format(**vars()))
while True:
conn, addr = s.accept()
with closing(conn), closing(conn.makefile('rb')) as file:
for byte in iter(lambda: file.read(1), b''):
# print numerical value of the byte as a decimal number
print(ord(byte), end=' ')
print("") # received all input from the client, print a newline
except KeyboardInterrupt:
print('Keyboard interrupt received, exiting.')
finally:
s.close()

Related

Communication between 2 python script in which the first one is continuously running

I have 2 python scripts.
To make it simple
1st script :
It is a simple infinite while loop in which a variable 'x' is being increased by 1(This script is always running)
Now what I want a 2nd script, when I call this script it should give me the present value of x
I read about multiprocessing ,pipe and queue but was not able to implement it
EDIT:
I tried the socket solution and I am getting errors
Client Side
import serial
import time
from multiprocessing import Process
import sys
import socket
s=socket.socket()
port=43470
s.connect(('127.0.0.1',port))
sertx = serial.Serial('COM4', 115200)
while 1:
for i in range(4):
msg = str(i+1)
# print('sending: ',msg.encode())
msgstat = 'A' + msg
#print(msgstat)
#print(type(msgstat))
tx_t = time.time()
sertx.write(msg.encode())
tx_t=str(tx_t)
s.send(tx_t.encode())
s.close()
time.sleep(0.001)
Error - File ".\tx.py", line 23, in
s.send(tx_t.encode())
OSError: [WinError 10038] An operation was attempted on something that is not a socket
PS C:\Users\ambuj\Documents\Python Scripts>
Server
import socket
s = socket.socket()
port = 43470 # make this any random port
s.bind(('127.0.0.1', port))
s.listen(5) # put the socket into listen mode
while True:
c, addr = s.accept()
data = c.recv(1024).decode("utf-8") # This data is received from the client script
print(data)
c.close()
You can surely achieve this thing using socket communication. Just create a server script like this which will listen to any incoming data to a specific port...
import socket
s = socket.socket()
port = 43470 # make this any random port
s.bind(('127.0.0.1', port))
s.listen(5) # put the socket into listen mode
while True:
c, addr = s.accept()
data = c.recv(1024).decode("utf-8") # This data is received from the client script
c.close()
Now in your client script, you have to connect to the socket that is binded in that port. Make a client script like this...
import socket
s = socket.socket()
port = 43470 # Use the same port number here as you did in the server script.
s.connect(('127.0.0.1', port))
s.send(b"This data will be received by the server!")
s.close()
You can do the reverse as well. So the server will be able to send the data to the client script. Its a two-way communication.
Remeber: This is just a simple demonstraction to make things work. In actual case, modification is much needed.

Is there a way to send two messages with socket

Im trying to send a messages from the server to the client
I tried deleting the .close and puting a while loop on print but it still doesn't won't to work
Client
import socket
s = socket.socket()
host = socket.gethostname()
port = 12345
s.connect((host, port))
while True:
print (s.recv(1024))
Server
import socket
s = socket.socket()
host = socket.gethostname()
port = 12345
s.bind((host, port))
s.listen(5)
while True:
c, addr = s.accept()
print ('Got connection from', addr)
x = str(input("ënter a message"))
data = x.encode()
c.send(data)
I expect the output to be 2 messages from the server but it is only sending 1 and then closing the connection
Switch your accept and while True: lines. Once you accept a connection, keep sending on the same connection.
Note that TCP is a streaming protocol. There is no concept of "messages", but just a bunch of bytes. If you send fast enough, such as:
c.send(b'abc')
c.send(b'def')
then recv(1024) could receive b'abcdef'. For more complex communication, you'll have to define a protocol and buffer recv until you are sure you have a complete message. A simple way in this case is read until you find a newline, or send a byte (or more) indicating the size of the total message before sending the actual message.

How can I know the number of clients connected to the server and return the number of the connected clients to the user?

I want to know these for I am getting crazy with this:
How can I do these:
1-If the server terminates the clients should terminate also. Your server should allow the administrator to close all connections (i.e. the server must wait for the user to terminate the program preferably through a menu interface)
2-In order to know the number of clients connected you will need to identify each client uniquely – this can be accomplished by using the pid that is uniquely assigned for each client connection (store these in a global list). These connections can change dynamically (i.e. clients can disconnect and reconnect) so you must maintain this list on the server.
This is my server side code:
Thanks in advance
import _thread
import socket
import sys
from datetime import datetime
def serveclient(c):
global v, nclient, vlock, nclientlock
while(True):
k=(c.recv(1)).decode('utf-8')
if(k==''):
break
if(k=='D'):
today = str(datetime.now().strftime('%Y-%m-%d'))
c.send(today.encode('utf-8'))
if(k=='T'):
tme = str(datetime.now().strftime('%H:%M:%S'))
c.send(tme.encode('utf-8'))
if(k=='X'):
<<<< # Here I should put the number of clients connected and echo back the number like the above code
vlock.acquire()
v+=k
vlock.release()
#Echo back
c.send(v.encode('utf-8'))
c.close() #End connection
nclientlock.acquire()
nclient-=1
nclientlock.release()
#Main driver code
listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
port = int(sys.argv[1])
listener.bind(('',port))
listener.listen(5)
#Initialize global data
v=''
vlock=_thread.allocate_lock()
nclient=10 #Max number of clients
nclientlock=_thread.allocate_lock()
#accept calls from clients
for i in range(nclient):
(client, ap) = listener.accept()
_thread.start_new_thread(serveclient, (client,))
listener.close()
while nclient >0:
pass #do nothing, just wait for client count to drop to zero
print('The final string is: ', v)
<<<<<<<<<<<<<<<<<<<<<<<<<This the Client Code>>>>>>>>>>>>>>>>>>>>>>>
#Client Program. Sends a single char at a time to the server until the client
#sends a '', this will terminate the client.
#
#usage: python server port
import socket
import sys
#create the socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = sys.argv[1] #Server info from cmd line
port = int(sys.argv[2]) #Port from cmd line
#Conncet to server
s.connect((host, port))
while(True):
#get letter
k = input('enter a letter: ')
s.send(k.encode('utf-8'))
if(k==''):
break
v=s.recv(1024) #receive upto 1024 bytes
print(v.decode('utf-8'))
s.close()
Just increment a count every time you accept a socket, and decrement it every time you close an accepted socket.

Client/Server Not Receiving Data in Python

I am totally new to socket programming.
I have a product and trying to connect.
I can send the data and see its result on product, but I cannot receive anything.
this is my script:
import socket
def ScktConn():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 5006))
# our local IP is 192.168.2.1, but it works even with 127.0.0.1, I don't know from where #it is coming
Freq=raw_input('Frequency(450-2500): ')
CmdF='0 ace_set_frequency C1 '+str(Freq)+' \r\n'
s.send(CmdF)
# so far I sent a tcl command to product to set the frequency and it works
s.send('0 ace_azplayer_remove_player XXX \r\n')
# sending another tcl command and works
s.send('0 ace_azplayer_add_player \r\n')
# here it is working too
s.send('0 ace_azplayer_add_ace XXX C1\r\n')
Path='C:/Users/AM_RJ/Desktop/gridview_script/PBF/4x4U_wocorr_SNR.csv'
s.send('0 ace_azplayer_load_csvfile AzPlayer1 '+Path+' \r\n')
# here I should receive some numbers, but always returning me 0!
#even if I send ('hello!') and use recv(1024), it returns 0!
csvid=s.recv(4096)
print csvid
Path2='0 ace_azplayer_edit_playback_file AzPlayer1 '+str(csvid)+' -linkConfiguration "4x4" \r\n'
print Path2
s.send(Path2)
After using recv(4096), I should receive some numbers, but it always returning me 0!
even if I send ('hello!') and use recv(1024), it returns 0!
I'm using python 2.7.
I am not even sure whether or not the server and client sides are correct in my script!
Please help me out about it.
You need more than one socket, here is a minimal example (which would need more work to be made robust). ScktConn spawns a new thread which creates a server socket that listens for the connection from s.
import socket
import threading
import time
address = ('127.0.0.1', 5007)
def ScktRecv():
r = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
r.bind(address)
r.listen(1)
conn, _ = r.accept()
csvid = conn.recv(4096)
print "recv: %s" % csvid
def ScktConn():
recv_thread = threading.Thread(target=ScktRecv)
recv_thread.start()
time.sleep(1)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(address)
# our local IP is 192.168.2.1, but it works even with 127.0.0.1, I don't know from where #it is coming
Freq=raw_input('Frequency(450-2500): ')
CmdF='0 ace_set_frequency C1 '+str(Freq)+' \r\n'
s.send(CmdF)

socket.send working only once in python code for an echo client

I have the following code for an echo client that sends data to an echo server using socket connection:
echo_client.py
import socket
host = '192.168.2.2'
port = 50000
size = 1024
def get_command():
#..Code for this here
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
while 1:
msg = get_command()
if msg == 'turn on':
s.send('Y')
elif msg == 'turn off':
s.send('N')
elif msg == 'bye bye':
break
else:
s.send('X')
data = s.recv(size)
print 'Received: ',data
s.close()
echo_server.py
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()
The problem im facing is that in the client s.send works only the first time even though its in an infinite loop. The client crashes with connection timed out, some time after the first send/receive has completed.
Why is s.send working only once ?. How can i fix this in my code ?
Please Help
Thank You
Your server code only calls recv once. You should call accept once if you only want to receive one connection, but then you need to loop calling recv and send.
Your problem is that you are blocking on the accept inside the server's loop.
This is expecting the server to accept connections from more than one client. If you want that, and for each client to send multiple commands, you would need to spawn a new thread (or process) after the accept, with a new while loop (for client communication) in that thread/process.
To fix your example to work with just one client, you need to move the accept outside the loop, like so:
client, address = s.accept()
while 1:
data = client.recv(size)
if data:
client.send(data)

Categories

Resources