i need to send a data each every X seconds from a client to a server with SOCKET, so i try this code:
for i in range(100):
localip = '127.0.0.1'
port = 5010
bufferSize = 1024
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)
client.connect((localip, port))
pacote = '2B4F08FE0F3B'
client.send(bytes(pacote, "utf-8"))
client.close()
time.sleep(10)
But in the serv i recive a package with nothing (' '). I need send 100x the same message to the serv, each 10 seconds. Somebody knows where is the mistake?
I have other Client.py where i put manually the data (with the input() ) and he works perfect, but now i need to do this automatically.
The client need to open a new connection to send each data.
But in the serv i recive a package with nothing (' ').
This is because the socket gets closed after sending the message, i.e. client.close().
I need send 100x the same message to the serv, each 10 seconds. Somebody knows where is the mistake?
If the server expects the client to create a single connection and then send many data over this connection before closing it, then the client should do exactly this. Instead your client opens a new connection for each new message and then closes the connection immediately after the message.
This means either you must fix the server to match the clients behavior or fix the client to match the servers behavior.
Related
I am trying to establish a client-server communication. The client is written in Ruby whereas the server is written in Python.
client.rb
require 'socket'
hostname = 'localhost'
port = 7778
s = TCPSocket.open(hostname, port)
s.write("2020-06-25T11:11:00+00:00 5 127.0.0.1 printer: event")
while line = s.gets
puts line.chop
end
s.close()
The ruby client sends a log to the Python server and tries to receive it back.
server.py
import socket
#Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#bind the socket to the port - tuple
server_address = ('localhost', 7778)
print('starting up on %s port %s' %server_address)
sock.bind(server_address)
#Listen for incoming connections
sock.listen(1)
while True:
print('waiting for a connection')
connection, client_address = sock.accept()
while True:
data = connection.recv(1024)
print('received "%s"' % data)
if data:
print('sending data back to the client')
connection.send(data)
else:
print('no more data from', client_address)
break
connection.close()
The log is sent to the python server and when the python server sends it back. When the ruby client receives it, it doesn't receive the full log.
example:
2020-06-25T11:11:00+00:00 5 127.0.0.1 printer: eve
I think this comes from the fact that TCP is a streaming protocol and we never know if we can get the full message each time.
Could you propose me a solution for both the client and the server so I can be sure they always receive the full message between each other? I would really appreciate it if anyone would help.
So the issue is that you're assuming the data received has a new line character - however the data you're sending is not terminated by a new line.
s.write("2020-06-25T11:11:00+00:00 5 127.0.0.1 printer: event") will not write the string with a new line character - you should use puts IO#puts
s.gets will return the data because the socket is closed by the python server after it has sent the data. So even getssays it will read the next line from the socket, in reality its just reading what remained in the buffer after the socket was closed.
line.chop will remove the last character, and you're using it here to strip a newline character (assuming that it has one from gets). However since there is no newline character it will remove the last character instead.
So the fix would be to replace in the ruby client s.write with s.puts.
I'm trying to understand how send and receive are working.
I was trying to send continuously data to a server and i noticed that the server would receive mixed bytes because i was sending to much data at a time. See my code:
Server:
import socket, struct
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("",1996))
server.listen(0)
c,d = server.accept()
while True:
data = c.recv(1024)
print( struct.unpack("i", data)[0] )
Client:
import socket, struct
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.connect(("192.168.1.4",1996))
while True:
data = 1
server.send( struct.pack("i", data) )
Then i change the while loops to this:
Server:
data = c.recv(1024)
print( struct.unpack("i", data)[0] )
c.send( str.encode("Server received your message. You now can continue
sending more data") )
Client:
data = 1
server.send( struct.pack("i", data) )
#Wait to secure the send.
server.recv(1024)
This is working. I'm making sure that the client won't send data before the
server already receive the previous send.
But what if i want to do the same for the server too? How can i make sure that the server will send bytes to the client in a safe way?
I already tried this and i notice that i created an infinity loop because(I used multi-threading in order to send and receive at the same time on the server):
client was sending some data and then waiting to get a signal from the server
that he can send again.
the server was getting some data then sending the signal and after that waiting for a signal from the user that he can send again.
But because the client was actually sending data again, the whole thing was going on again and this caused me an infinity talk-reply loop.
So what can i do to make a continuously conversation between two sockets without mixing the bytes together?
Your problem is caused by Nagle algorithm which works by combining a number of small outgoing messages, and sending them all at once as TCP is a stream protocol. You can enable TCP_NODELAY socket option by calling sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) to sent data as soon as possible, even if there is only a small amount of data. And on the receiver side, it isn't going to get one packet at a time either, you must implement message boundaries itself if you want "continuous conversation between two sockets without mixing the bytes together".
I am using TCP sockets to communicate between my server and clients. The server code and socket code are as below:
server:
from socket import *
HOST = 'xx.xx.xx.xx'
PORT = 1999
serversocket = socket(AF_INET,SOCK_STREAM)
serversocket.bind((HOST,PORT))
print 'bind success'
serversocket.listen(5)
print 'listening'
while True:
(clientsocket, address) = serversocket.accept()
print ("Got client request from",address)
#clientsocket.send('True')
data = clientsocket.recv(1024)
print data
clientsocket.send('True')
clientsocket.close()
client:
import socket
import sys
# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Connect the socket to the port on the server given by the caller
server_address = ('xx.xx.xx.xx', 1999)
print >>sys.stderr, 'connecting to %s port %s' % server_address
sock.connect(server_address)
try:
message = 'This is the message. It will be repeated.'
print >>sys.stderr, 'sending'
for x in range (0,1):
name=raw_input ('what is ur name')
print type(name)
sock.send(name)
print sock.recv(1024)
finally:
sock.close()
I am able to communicate with the server from client and able to send and receive data. But the problem I am facing is that I am not able to send and receive data continuously from the server. I have to restart my client code on my laptop to send and receive data again from the server. The way the above client code is working is that when I give a keyboard input, then the socket sends data to server and server responds back. But in the client code, in the for loop if I do two iterations, for the second iteration the data I enter from keyboard is not reaching server. I need to restart my client code to send data again. How do I fix this ?
Also, when once client is connected to the server, the other cannot connect to the server. Any ideas on how to do this ?
You need to design and implement a protocol that specifies what each side is supposed to do and then implement that protocol. You're expecting it to work by magic.
For example:
data = clientsocket.recv(1024)
I suspect you are expecting this to receive a "message". But TCP has no notion of messages. If you need to send and receive messages, you need to define precisely what a "message" is for your protocol and write code to send and receive them.
It may be helpful to look at the specifications for other protocols that use TCP such as HTTP, FTP, or IRC. It really is worth the time to write out a specification of your protocol before you write any code. It will save a lot of pain.
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.
I'm building a game-server in Python. The functionality is pretty well-defined. The server will listen on the port 6000 and a remote client will send a request. Then the server will establish a connection to the client's port 7000. From then on, the client will keep sending 'requests' (basically, strings such as "UP#", "DOWN#", "SHOOT#" etc.) to server's port 6000.
This is the problem. I have made a 'server' who listens on the port 6000. This means I cannot bind a client to the same port. Is there a way that I can get the data string of an incoming request in a server? So far, I only have this.
What am I doing wrong here? Any workarounds for this issue? In short, can I read the incoming request string from a client in the server code?
Thanks in advance.
def receive_data(self):
errorOccured = False
connection = None
try:
listener = socket.socket() # Create a socket object.
host = socket.gethostname()
port = 6000 # The port that the server keeps listening to.
listener.bind(('', port))
# Start listening
listener.listen(5)
statement = ("I:P0:7,6;8,1;0,4;3,8;3,2;1,6:5,4;9,3;8,7;2,6;1,4;2,7;6,1;6,3:2,1;8,3;5,8;9,8;7,2;0,3;9,4;4,8;7,1;6,8#\n","S:P0;0,0;0#","G:P0;0,0;0;0;100;0;0:4,3,0;5,4,0;3,8,0;2,7,0;6,1,0;5,8,0;1,4,0;1,6,0#", "C:0,5:51224:824#","G:P0;0,0;0;0;100;0;0:4,3,0;5,4,0;3,8,0;2,7,0;6,1,0;5,8,0;1,4,0;1,6,0#","G:P0;0,1;2;0;100;0;0:4,3,0;5,4,0;3,8,0;2,7,0;6,1,0;5,8,0;1,4,0;1,6,0#")
# This is just game specific test data
while True:
c, sockadd = listener.accept() # Establish connection with client.
print 'incoming connection, established with ', sockadd
i = 0 # Just a counter.
while i<len(statement):
try:
self.write_data(statement[i], sockadd[0])
time.sleep(1) # The game sends updates every second to the clients
i = i + 1
#print listener.recv(1024) -- this line doesn't work. gives an error
except:
print "Error binding client"
c.close() # Close the connection
return
except:
print "Error Occurred"
I'm going to answer it because I got some help and figured it out.
The most basic thing I can do is to use the client connection which is c for this purpose. In here, instead of the commented line data=listener.recv(1024) I should have used data= c.recv(1024). Now it works.
Another way is to use SocketServers with a StreamingRequestHandler. While this is ideal for usage of typical servers, if a lot of objects are involved it could reduce the flexibility.