I'm new to python and sockets and am trying to write an echoing client/server socket. I have written the server so that 30% of the packets are lost. I programmed my client to timeout after one second since the packet could be lost. However, whenever I run my client socket, my output is 100% REQUEST TIMED OUT. I'm assuming I'm getting this output because my server is never receiving the message. I've looked over my code multiple times and cannot figure out why I am constantly getting this output. Below is my code for my server and client sockets. Any help would be appreciated.
我是python和套接字的新手,我正在尝试编写一个回显客户端/服务器套接字。我编写了服务器,以便丢失30%的数据包。由于数据包可能丢失,我在一秒钟后将客户端编程为超时。但是,每当我运行客户端套接字时,我的输出都是100%REQUEST TIMED OUT。我假设我得到这个输出,因为我的服务器永远不会收到消息。我多次查看我的代码,无法弄清楚为什么我不断得到这个输出。下面是我的服务器和客户端套接字的代码。任何帮助,将不胜感激。
Server Socket:
服务器套接字:
# We will need the following module to generate randomized lost packets
import random
from socket import *
# Create a UDP socket
# Notice the use of SOCK_DGRAM for UDP packets
serverSocket = socket(AF_INET, SOCK_DGRAM)
# Assign IP address and port number to socket
serverSocket.bind(('', 12000))
while True:
# Generate random number in the range of 0 to 10
rand = random.randint(0, 10)
# Receive the client packet along with the address it is coming from
message, address = serverSocket.recvfrom(1024)
# Capitalize the message from the client
message = message.upper()
# If rand is less is than 4, we consider the packet lost and do notrespond
if rand < 4:
continue
# Otherwise, the server responds
serverSocket.sendto(message, address)
Client Socket:
客户端套接字:
import time
from socket import *
pings = 1
#Send ping 10 times
while pings < 11:
#Create a UDP socket
clientSocket = socket(AF_INET, SOCK_DGRAM)
#Set a timeout value of 1 second
clientSocket.settimeout(1)
#Ping to server
message = 'test'
addr = ("127.0.0.1", 12000)
#Send ping
start = time.time()
clientSocket.sendto(message, addr)
#If data is received back from server, print
try:
data, server = clientSocket.recvfrom(1024)
end = time.time()
elapsed = end - start
print data + " " + pings + " "+ elapsed
#If data is not received back from server, print it has timed out
except timeout:
print 'REQUEST TIMED OUT'
pings = pings - 1
2 个解决方案
#1
17
I tested your code, and it works as expected on my machine. Your issue might not be your code. It could be a firewall or something else blocking all the packets on the loopback interface (127.0.0.1). Depending on your operating system, try testing with a packet monitor like Wireshark.
我测试了你的代码,它在我的机器上按预期工作。您的问题可能不是您的代码。它可能是防火墙或其他阻止环回接口(127.0.0.1)上的所有数据包的东西。根据您的操作系统,尝试使用Wireshark等数据包监视器进行测试。
Also, here are a few suggestions on how to improve your code to be more Pythonic:
另外,这里有一些关于如何将代码改进为Pythonic的建议:
Server
服务器
import random
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind(('', 12000))
while True:
rand = random.randint(0, 10)
message, address = server_socket.recvfrom(1024)
message = message.upper()
if rand >= 4:
server_socket.sendto(message, address)
Client
客户
import time
import socket
for pings in range(10):
client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client_socket.settimeout(1.0)
message = b'test'
addr = ("127.0.0.1", 12000)
start = time.time()
client_socket.sendto(message, addr)
try:
data, server = client_socket.recvfrom(1024)
end = time.time()
elapsed = end - start
print(f'{data} {pings} {elapsed}')
except socket.timeout:
print('REQUEST TIMED OUT')
#2
1
Here is an alternative with asyncio.
这是asyncio的替代方案。
import asyncio
import random
class EchoServerProtocol:
def connection_made(self, transport):
self.transport = transport
def datagram_received(self, data, addr):
message = data.decode()
print('Received %r from %s' % (message, addr))
rand = random.randint(0, 10)
if rand >= 4:
print('Send %r to %s' % (message, addr))
self.transport.sendto(data, addr)
else:
print('Send %r to %s' % (message, addr))
self.transport.sendto(data, addr)
loop = asyncio.get_event_loop()
print("Starting UDP server")
# One protocol instance will be created to serve all client requests
listen = loop.create_datagram_endpoint(
EchoServerProtocol, local_addr=('127.0.0.1', 12000))
transport, protocol = loop.run_until_complete(listen)
try:
loop.run_forever()
except KeyboardInterrupt:
pass
transport.close()
loop.close()
#1
17
I tested your code, and it works as expected on my machine. Your issue might not be your code. It could be a firewall or something else blocking all the packets on the loopback interface (127.0.0.1). Depending on your operating system, try testing with a packet monitor like Wireshark.
我测试了你的代码,它在我的机器上按预期工作。您的问题可能不是您的代码。它可能是防火墙或其他阻止环回接口(127.0.0.1)上的所有数据包的东西。根据您的操作系统,尝试使用Wireshark等数据包监视器进行测试。
Also, here are a few suggestions on how to improve your code to be more Pythonic:
另外,这里有一些关于如何将代码改进为Pythonic的建议:
Server
服务器
import random
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind(('', 12000))
while True:
rand = random.randint(0, 10)
message, address = server_socket.recvfrom(1024)
message = message.upper()
if rand >= 4:
server_socket.sendto(message, address)
Client
客户
import time
import socket
for pings in range(10):
client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client_socket.settimeout(1.0)
message = b'test'
addr = ("127.0.0.1", 12000)
start = time.time()
client_socket.sendto(message, addr)
try:
data, server = client_socket.recvfrom(1024)
end = time.time()
elapsed = end - start
print(f'{data} {pings} {elapsed}')
except socket.timeout:
print('REQUEST TIMED OUT')
#2
1
Here is an alternative with asyncio.
这是asyncio的替代方案。
import asyncio
import random
class EchoServerProtocol:
def connection_made(self, transport):
self.transport = transport
def datagram_received(self, data, addr):
message = data.decode()
print('Received %r from %s' % (message, addr))
rand = random.randint(0, 10)
if rand >= 4:
print('Send %r to %s' % (message, addr))
self.transport.sendto(data, addr)
else:
print('Send %r to %s' % (message, addr))
self.transport.sendto(data, addr)
loop = asyncio.get_event_loop()
print("Starting UDP server")
# One protocol instance will be created to serve all client requests
listen = loop.create_datagram_endpoint(
EchoServerProtocol, local_addr=('127.0.0.1', 12000))
transport, protocol = loop.run_until_complete(listen)
try:
loop.run_forever()
except KeyboardInterrupt:
pass
transport.close()
loop.close()