I'm newbie in Python.
I wrote a socket server. It can read and send json-data. But I need to do it with select to extend it.
But I have no idea how to do it. I can't understand examples from the Internet - they have input(), sys.stdin and so on (for what??)
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('0.0.0.0', 8888,))
server_socket.listen(5)
while True:
client, address = server_socket.accept()
data = client.recv(1024)
print('received:', data.decode('utf-8'))
sending_data = bytes(generate_json(), 'utf-8')
print(sending_data)
client.send(sending_data)
client.close()
Related
I want to set up a simple echo server that just echoes back whatever the client sends to it. However, currently the server disconnects (the server socket closes) after it echoes back the first client message. I want to be able to "chat" continuously with the server, where the server just echoes back several consecutive messages I send without disconnecting; e.g.:
"Hi there!"
"Echoing: Hi there!"
"How are you?"
"Echoing: How are you?"
"Cheers!"
"Echoing: Cheers!"
etc.
Currently I have the following code:
server.py:
import socket
HOST = '127.0.0.1'
PORT = 5000
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept()
with conn:
while True:
data = conn.recv(1024)
if not data:
break
conn.sendall(data)
client.py:
import socket
HOST = '127.0.0.1'
PORT = 5000
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
s.sendall(b'Hello, world')
data = s.recv(1024)
print('Echoing: ', repr(data))
The server, however, disconnects after it echoes back the first client message (probably because of the if not data: break statement).
P.S. I'd appreciate any additional explanations which might be necessary - this example has educational purposes, so I'm not (only) after getting the code running.
Thanks!
server.py:
import socket
HOST = '127.0.0.1'
PORT = 5000
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept()
with conn:
while True:
data = conn.recv(1024)
if data.decode() == "bye":
break
conn.sendall(data)
conn, addr = s.accept()
I will show you the code I created then talk you through it:
Server:
import socket
HOST = '127.0.0.1'
PORT = 5000
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept()
with conn:
while True:
data = conn.recv(1024)
conn.sendall(data)
For the server I removed:
if not data:
break
It simply wasn't working for me. If you know your message is going to be less than the 1024 bytes( which here it is) it's unnecessary. But if you want a longer message change that value to a bigger number to accommodate. So yes you were right in suspecting it was that line.
Client:
import socket
HOST = '127.0.0.1'
PORT = 5000
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
print("Connected")
while True:
print("Sending data")
s.sendall(b'Hello, world')
print("Recieving data")
data = s.recv(1024)
print('Echoing: ', repr(data))
For the client side I just added the send and receive process into a loop.
Things to note:
This only works for me when run through the terminal, I don't know if you know how to do that so sorry if you do, here's a link explaining:
https://www.wikihow.com/Use-Windows-Command-Prompt-to-Run-a-Python-File
I assumed you use Windows.
You will need to follow the process for both your client.py programme and server.py programme. Make sure you run the server.py programme first.
This will cause an infinite loop of sending and receiving. Press Ctrl+C to terminate.
I hope this solves your problem and you can edit the code accordingly. Any further problems please do comment and I'll try to get back to you.
Maybe use sleep instead of break
if not data:
time.sleep(1)
continue
You have to import time module for this.
I copied the echo server example from the python documentation and it's working fine. But when I edit the code, so it wont send the data back to the client, the socket.recv() method doesn't return when it's called the second time.
import socket
HOST = ''
PORT = 50007
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print('Connected by', addr)
while True:
data = conn.recv(1024)
if not data: break
conn.sendall(b'ok')
conn.close()
In the original version from the python documentation the while loop is slightly different:
while True:
data = conn.recv(1024)
if not data: break
conn.sendall(data)
Client's code:
import socket
HOST = 'localhost'
PORT = 50007
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall(b'Hello, world')
data = s.recv(1024)
s.close()
print('Received', repr(data))
TCP sockets are streams of data. There is no one-to-one correlation between send calls on one side and receive calls on the other. There is a higher level correlation based on the protocol you implement. In the original code, the rule was that the server would send exactly what it received until the client closed the incoming side of the connection. Then the server closed the socket.
With your change, the rules changed. Now the server keeps receiving and discarding data until the client closes the incoming side of the connection. Then the server sends "ok" and closes the socket.
A client using the first rule hangs because its expecting data before it closes the socket. If it wants to work with this new server rule, it has to close its outgoing side of the socket to tell the server its done, and then it can get the return data.
I've updated the client and server to shutdown parts of the connection and also have the client do multiple recv's in case the incoming data is fragmented. Less complete implementations seem to work for small payloads because you are unlikely to get fragmentation, but break horribly in real production code.
server
import socket
HOST = ''
PORT = 50007
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print('Connected by', addr)
while True:
data = conn.recv(1024)
if not data: break
conn.sendall(b'ok')
conn.shutdown(socket.SHUT_WR)
conn.close()
client
import socket
HOST = 'localhost'
PORT = 50007
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall(b'Hello, world')
s.shutdown(socket.SHUT_WR)
data = b''
while True:
buf = s.recv(1024)
if not buf:
break
data += buf
s.close()
print('Received', repr(data))
The number of receive and send operations have to match because they are blocking. This is the flow diagram for your code:
Server listen
Client connect
Server receive (this waits until a message arrives at the server) [1]
Client send 'Hello world' (received by [1])
Server receive (because there was data received) [2]
Client receive [3]
Because the server and the client are blocked now, no program can continue any further.
The fix would be to remove the client's receive call because you removed the server's send call.
A simple demo of socket programming in python:
server.py
import socket
host = '127.0.0.1'
port = 8000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(1)
conn, addr = s.accept()
while True:
data = conn.recv(1024)
print 'Received:', data
if not data:
break
conn.sendall(data)
print 'Sent:', data
conn.close()
client.py
import socket
host = '127.0.0.1'
port = 8000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.sendall('Hel')
s.sendall('lo world!')
print 'Received:', s.recv(1024)
s.close()
Now code work well. However, the client may not know if server will always send back every time. I tried symmetric code of while-loop in server.py
client_2.py
import socket
host = '127.0.0.1'
port = 8000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.sendall('Hel')
s.sendall('lo world!')
while True:
data = s.recv(1024)
if not data:
break
print 'Received:', data
s.close()
This code will block at
data = s.recv(1024)
But in server.py, if no data received, it will be blank string, and break from while-loop
Why it does not work for client? How can I do for same functionality without using timeout?
You can set a socket to non-blocking operation via socket.setblocking(false), which is equivalent to socket.settimeout(0). Solving this "without using timeout" is impossible.
Greetings and apologies in advance if it looks a real novice question. I am new to python, or programming for that matter. I am writing a code that sends data from client to server. The data I need to send is from an csv file, which has around 10,000 rows. Currently I am sending the data in a large buffer as a whole, but I would prefer to send it row by row and also receive it the same way. I am not sure if I should use the split() function or there are any better ways to do the same thing.
The client...
import socket
HOST = 'server IP'
PORT = 42050
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
f = open('csvfile.csv', 'rb')
l = f.read(409600)
while True:
print l
s.send(l)
break
f.close()
print "Done Sending"
s.close()
The server...
import socket
HOST = 'local IP'
PORT = 42050
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
print "Server running", HOST, PORT
s.listen(5)
conn, addr = s.accept()
print'Connected by', addr
while True:
data = conn.recv(409600)
print repr(data)
if not data: break
print "Done Receiving"
conn.close()
Thanks in advance for the help.
im not sure what your question actually is ... but its pretty easy to send and receive lines
#client.py
for line in open("my.csv"):
s.send(line)
#server.py
def read_line(sock):
return "".join(iter(lambda:sock.recv(1),"\n"))
iter(lambda:sock.recv(1),"\n")
is essentially the same as
result = ""
while not result.endswith("\n"): result += sock.recv(1)
Trying to create my first client-server application, I came across an error. This code is exactly the same as in the documentation, but I have problems.
Server:
import socket
HOST = 'localhost'
PORT = 9090
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print 'Connected by', addr
while True:
data = conn.recv(1024)
if not data: break
print data
conn.close()
Client:
import socket
HOST = 'localhost'
PORT = 9090
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall('Hello, world')
s.close()
After execution, I don't see the message print Connected by, addr and print data in the server part.
I use Windows 7, Komodo Firewall (I tried to close the firewall, but it didn't solve the problem), Avast Antivirus, Python 2.7.
Very interesting, that there are no errors, but the output just doesn't work.
Also, my server application just freezes until the client connects to the server. Can this be solved just using threading?
Thanks in advance.
You need to accept() and print inside the loop. (or use two loops). I'm not very familiar with socket programming in Python but I'm guess it would look something like this. (completely untested!)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
while True:
conn, addr = s.accept()
print 'Connected by', addr
while True:
data = conn.recv(1024)
if not data:
break
print data
conn.close()
+1 to Cfreak. Basically what is happening with data is that it is getting assigned an empty string which causes the loop to break. So putting the print statement in the loop fixes the problem. Assuming you need to access that data after the loop terminates try something like
data = []
while True:
datum = conn.recv(1024)
data.append(datum)
if not datum: break
print " ".join(data)
Here is the code I am running and my computer, and it works
client
import socket
HOST = 'localhost'
PORT = 9090
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall('Hello, world')
s.close()
server
import socket
HOST = 'localhost'
PORT = 9090
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print 'Connected by', addr
data = []
while True:
datum = conn.recv(1024)
data.append(datum)
if not datum: break
print " ".join(data)
conn.close()
so I don't think it is a problem with your code... if you have a machine without a firewall/antivirus on it try the program on that machine.