gpt4 book ai didi

python - 客户端(python 程序)没有收到服务器(c 程序)返回的响应?

转载 作者:太空宇宙 更新时间:2023-11-04 03:13:14 28 4
gpt4 key购买 nike

我有一个在服务器端工作的 UDP 套接字应用程序。为了测试服务器端,我编写了一个简单的 python 客户端程序,它发送消息“hello world how are you”。服务器随后应接收消息,将其转换为大写并发送回客户端。问题就在这里:我可以在调试时观察到服务器正在接收消息、应用转换、发回响应并最终等待另一条消息。然而,python 客户端没有收到消息,而是无休止地等待服务器的响应。

我通过网络发现(一个选项)为了让客户端接收到它需要绑定(bind)到服务器的响应,这与我在教科书(Linux 编程接口(interface))中看到的背道而驰。尽管如此,我尝试将客户端绑定(bind)到服务器,但 python 程序无法在绑定(bind)线上连接(不知道我是否正确)。 Python 版本为 2.7.5。客户端程序在 RedHat 上运行,服务器在 Angstrom 的目标模块上运行(它是为 32 位处理器交叉编译的)。

这是客户端的代码:

import socket
import os

UDP_IP = "192.168.10.4"
UDP_PORT = 50005

#dir_path = os.path.dirname(os.path.realpath(__file__))

MESSAGE = "hello world how are you"

print "UDP target IP: ", UDP_IP
print "UDP target port: ", UDP_PORT
print "message: ", MESSAGE

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#sock.bind((UDP_IP, UDP_PORT))
print "Sending message..."
sock.sendto(MESSAGE, (UDP_IP, UDP_PORT))
print "Message sent!"
print "Waiting for response..."
data = sock.recv(1024)

print "Received", repr(data)

这是服务器的代码:

void server_side(void)
{
printf("Server start up.\n");

struct sockaddr_in svaddr;
struct sockaddr_in claddr;
int sfd;
int j;
ssize_t numBytes;
socklen_t len;
char buf[BUF_SIZE];
char claddrStr[INET_ADDRSTRLEN];

//int output = open("test_output.txt", O_WRONLY|O_CREAT, 0664);

printf("Creating new UDP socket...\n");

sfd = socket(AF_INET, SOCK_DGRAM, 0); /* Create Server Socket*/
if (sfd == -1)
{
errExit("socket");
}

printf("Socket has been created!\n");

memset(&svaddr, 0, sizeof(struct sockaddr_in));

svaddr.sin_family = AF_INET;
svaddr.sin_addr.s_addr = htonl(INADDR_ANY);
svaddr.sin_port = htons(PORT_NUM);

printf("Binding in process...\n");

if (bind(sfd, (struct sockaddr *) &svaddr, sizeof(struct sockaddr_in))
== -1)
{
errExit("bind");
}

printf("Binded!\n");

/* Receive messages, convert to upper case, and return to client.*/

for(;;)
{
len = sizeof(struct sockaddr_in);
numBytes = recvfrom(sfd, buf, BUF_SIZE, 0,
(struct sockaddr *) &claddr, &len);
if (numBytes == -1)
{
errExit("recvfrom");
}
if (inet_ntop(AF_INET, &claddr.sin_addr, claddrStr,
INET_ADDRSTRLEN) == NULL)
{
printf("Couldn't convert client address to string.\n");
}
else
{
printf("Server received %ld bytes from (%s, %u).\n", (long)
numBytes,
claddrStr, ntohs(claddr.sin_port));
}

claddr.sin_port = htons(PORT_NUM);

for (j = 0; j< numBytes; j++)
{
buf[j] = toupper((unsigned char) buf[j]);
}

if (sendto(sfd, buf, numBytes, 0, (struct sockaddr *) &claddr, len)
!= numBytes)
{
fatal("sendto");
}
}
}

同样的问题是我没有收到响应并在客户端打印回消息。我应该收到所有大写字母的相同消息。我觉得我错过了一个小细节。感谢您的帮助!

最佳答案

快速而肮脏:

从您的 C 代码中删除这一行:

claddr.sin_port = htons(PORT_NUM);

现在为什么:

当您在 python 脚本中发送消息时,您的操作系统将填充 UDP packet使用您指定的目标 IP 地址和端口,您在源 IP 字段中使用的机器的 IP 地址,最后是操作系统“随机”分配的源端口。请注意,这与目标端口不是同一个端口,即使是这样,您怎么知道哪个程序将收到源消息?(两者都会听到来自同一端口的消息)幸运的是,这不是可能。

现在,当您的 C 代码收到此数据包时,它将知道是谁发送了消息,并且您可以通过 recvfrom 填充的 sockaddr 结构访问此信息。如果你想发回一些信息,你必须发送一个目标端口(服务器看到的)等于客户端看到的源端口的数据包,这又不是你正在监听的相同端口服务器。通过执行 claddr.sin_port = htons(PORT_NUM),您可以设置用服务器端口覆盖包含客户端源端口的字段,当您尝试发送此数据包时,可能会发生两件事:

  • 如果客户端从同一台计算机运行,目标 IP 和源 IP 将相同,您刚刚设置了目标端口成为服务器正在监听的端口,因此您将拥有一个消息循环。
  • 如果在不同的计算机上运行,​​数据包将由客户端计算机收到,但可能不会有任何程序在该端口上等待消息,因此它被丢弃。

一个半生不熟的比喻:你收到一个 friend 的来信,但是给他回信的时候,你把他家的门牌号换成了你家的门牌号……没有多大意义。唯一不同的是,你这位 friend 的 Action 比较大,每个字母的编号可能不同,但这并不重要。

理论上,如果要接收回数据就必须绑定(bind),此时绑定(bind)相当于监听那个端口。这个答案阐明了为什么在这种情况下没有必要:https://stackoverflow.com/a/14243544/6253527

如果您使用的是 Linux,您可以使用 sudo ss -antup | 查看操作系统为 UDP 套接字分配的端口。 grep python

关于python - 客户端(python 程序)没有收到服务器(c 程序)返回的响应?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54311678/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com