udp, datagram sockets

7

7stud

I'm trying to understand datagrams. My client program sends a message
to the server, and then the server infinitely loops over the recv() to
make sure all the data was received. I'm trying to use an * to signal
the end of the message, so that the server can break out of the
infinite while loop used to check the recv(). However, my server
repeatedly outputs the client message over and over again. Can anyone
tell me why?

When I start the server, I get the following debug output as
expected:

---------
debug: start outer while loop
#this infinite while loop endlessly listens for messages from the
client

debug: recv while loop
#this infinite while loop checks to make sure the whole message was
received
-----------

and then the recv() blocks and waits for data to be sent by the
client. But when I start the client, the server repeatedly outputs the
client message over and over again. My expectation was that after
processing the message from the client, the server would block the
next time it executed the recv() statement and wait for more data from
the client.

client:
----------
import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

message = "hello*" #asterisk to delimit end of message
msg_size = len(message)
total_sent = 0

print "debug:", total_sent, msg_size

while total_sent < msg_size:
size_sent = s.sendto(message[total_sent:], ("localhost", 7777) )
total_sent += size_sent

print "debug:", total_sent, msg_size

print 'debug: while loop ended'
s.close()
-----------

Here's the client output:

-------------
debug: 0 6
debug: 6 6
debug: while loop ended
---------------


server:
------------------
import socket
import sys

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(("", 7777))

try:
while True: #This loop listens endlessly for messages.
print "debug: start outer while loop"

#Receive messages from client:
my_list = []
while True: #This loop checks to see if the whole message was
received.
print "debug: recv while loop"

data = s.recv(1024)
my_list.append(data)

if data.rfind("*"):
message = "".join(my_list)
print "Received message:\n%s" % message[:-1]
break


#Send messages back to client:
total_sent = 0
while total_sent < len(message):
print "debug: send while loop"

size_sent = s.sendto(message[total_sent:], ("localhost",
7777) )
total_sent += size_sent

print "debug:", total_sent, len(message)

finally:
s.close()
--------------------------

Here's the server output:

---------------
debug: start outer while loop
debug: recv while loop
Received message:
hello
debug: send while loop
debug: 6 6
debug: start outer while loop
debug: recv while loop
Received message:
hello
debug: send while loop
debug: 6 6
.....
.....
.....
------------------
 
T

Thomas Jollans

I'm trying to understand datagrams. My client program sends a message
to the server, and then the server infinitely loops over the recv() to
make sure all the data was received. I'm trying to use an * to signal
the end of the message, so that the server can break out of the
infinite while loop used to check the recv(). However, my server
repeatedly outputs the client message over and over again. Can anyone
tell me why?

When I start the server, I get the following debug output as
expected:

---------
debug: start outer while loop
#this infinite while loop endlessly listens for messages from the
client

debug: recv while loop
#this infinite while loop checks to make sure the whole message was
received
-----------

and then the recv() blocks and waits for data to be sent by the
client. But when I start the client, the server repeatedly outputs the
client message over and over again. My expectation was that after
processing the message from the client, the server would block the
next time it executed the recv() statement and wait for more data from
the client.

client:
----------
import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

message = "hello*" #asterisk to delimit end of message
msg_size = len(message)
total_sent = 0

print "debug:", total_sent, msg_size

while total_sent < msg_size:
size_sent = s.sendto(message[total_sent:], ("localhost", 7777) )
total_sent += size_sent

print "debug:", total_sent, msg_size

print 'debug: while loop ended'
s.close()
-----------

Here's the client output:

-------------
debug: 0 6
debug: 6 6
debug: while loop ended
---------------


server:
------------------
import socket
import sys

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(("", 7777))

try:
while True: #This loop listens endlessly for messages.
print "debug: start outer while loop"

#Receive messages from client:
my_list = []
while True: #This loop checks to see if the whole message was
received.
print "debug: recv while loop"

data = s.recv(1024)
my_list.append(data)

if data.rfind("*"):
message = "".join(my_list)
print "Received message:\n%s" % message[:-1]
break


#Send messages back to client:
total_sent = 0
while total_sent < len(message):
print "debug: send while loop"

size_sent = s.sendto(message[total_sent:], ("localhost",
7777) )
total_sent += size_sent

print "debug:", total_sent, len(message)

finally:
s.close()
--------------------------

Here's the server output:

---------------
debug: start outer while loop
debug: recv while loop
Received message:
hello
debug: send while loop
debug: 6 6
debug: start outer while loop
debug: recv while loop
Received message:
hello
debug: send while loop
debug: 6 6
....
....
....
------------------

You don't make any attempt to break out of the outer loop. (break breaks the
innermost loop)
 
7

7stud

You don't make any attempt to break out of the outer loop. (break breaks the
innermost loop)

By design. My server stands ready to process any and all messages
forever. The problem I'm having is that my server processes the same
message forever.
 
7

7stud

The network is probably dropping some of your data, causing the server
to never see the termination marker.

As far as I can tell, the output disproves that notion. If the
termination character were somehow lost in transmission, then this
statement:

print "Received message:\n%s" % message[:-1]

would produce the output:


Received message:
hell

since the print statement chops off the last character of the received
data.
 
C

Carsten Haese

server:
------------------
import socket
import sys

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(("", 7777))
[...]
#Send messages back to client:
total_sent = 0
while total_sent < len(message):
print "debug: send while loop"

size_sent = s.sendto(message[total_sent:], ("localhost",
7777) )
total_sent += size_sent

print "debug:", total_sent, len(message)

I don't think that sending the datagram to port 7777 on localhost sends
the message back to the client. I'm guessing the server is sending the
message back to itself, which throws it into the infinite feedback loop
you're experiencing.

HTH,
 
A

anethema

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(("", 7777))
[...]
#Send messages back to client:
total_sent = 0
while total_sent < len(message):
print "debug: send while loop"
size_sent = s.sendto(message[total_sent:], ("localhost",
7777) )
total_sent += size_sent
print "debug:", total_sent, len(message)

I don't think that sending the datagram to port 7777 on localhost sends
the message back to the client. I'm guessing the server is sending the
message back to itself, which throws it into the infinite feedback loop
you're experiencing.

HTH,

Yes, you want to use the socket.recvfrom() method, store the address,
and send the response to that address. Your code is indeed repeatedly
sending itself the received message.

You want to changeto
data, recv_addr = s.recvfrom(1024)

and
size_sent = s.sendto(message[total_sent:], ("localhost",
7777) )
to
size_sent = s.sendto(message[total_sent:], recv_addr)

However, your client closes immediately after sending all its data, so
it will never receive that message.
 
7

7stud

I don't think that sending the datagram to port 7777 on localhost sends
the message back to the client. I'm guessing the server is sending the
message back to itself, which throws it into the infinite feedback loop
you're experiencing.

Thanks.

Yes, you want to use the socket.recvfrom() method, store the address,
and send the response to that address. Your code is indeed repeatedly
sending itself the received message.

You want to change
data = s.recv(1024)

to

data, recv_addr = s.recvfrom(1024)

and
size_sent = s.sendto(message[total_sent:], ("localhost",
7777) )

to

size_sent = s.sendto(message[total_sent:], recv_addr)

Thanks for the details.

However, your client closes immediately after sending all its data, so
it will never receive that message.

Yes, I commented out the recv() part of the client to debug the
infinite loop I was experiencing. When I add that back to the client
everything works as it should.

Thanks to both of you again.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

sockets -- basic udp client 12
UDP queue size 0
Can't get UDP example to work 7
error in except 2
Python recv loop 7
Problem receiving UDP broadcast packets. 34
icmp and raw sockets in python 1
UNIX datagram sockets 29

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top