【发布时间】:2020-06-16 09:49:56
【问题描述】:
我正在尝试编写一个服务器程序,它只显示它通过 udp 从任何人那里收到的任何原始数据。客户端可以随时向其发送一些数据。除了“套接字错误:资源暂时不可用”之外没有出现任何错误,换句话说,这意味着recvfrom 没有要接收的数据(因为它可能没有收到任何数据包)。
客户端只是发送“测试!”到 127.0.0.0:12345,而服务器在端口 12345 上使用非阻塞套接字进行侦听。值得注意的是,我在 linux 上。
为什么server 不显示显然是从client 发送的数据包?我看不出我错过了什么。
common.h
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
typedef struct sockaddr_in sockaddr_in;
typedef struct sockaddr sockaddr;
int createSocket(uint16_t port)
{
int handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (handle <= 0)
{
printf("failed to create socket\n");
return 0;
}
sockaddr_in address;
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(port);
if (bind(handle, (const sockaddr*)&address, sizeof(sockaddr_in)) < 0)
{
printf("failed to bind socket\n");
return 0;
}
int nonBlocking = 1;
if (fcntl(handle, F_SETFL, O_NONBLOCK, nonBlocking) == -1)
{
printf("failed to set non-blocking\n");
return 0;
}
return handle;
}
int sendData(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint16_t port, int handle, char* packet_data, int packet_size)
{
uint32_t address = (a << 24) | (b << 16) | (c << 8) | d;
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(address);
addr.sin_port = htons(port);
int sent_bytes = sendto(handle, (const char*)packet_data, packet_size, 0, (sockaddr*)&address, sizeof(sockaddr_in));
if (sent_bytes != packet_size)
{
printf("failed to send packet (%d/%d)\n", sent_bytes, packet_size);
return 0;
}
}
server.c
#include "common.h"
#include <time.h>
void main(void){
int socket = createSocket(12345);
if (!socket){
perror("Socket error");
}
int true=1;
setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (const void*)&true, 1);
// so that we can immediately reuse the port if the server stops running
char buffer[100] = "No data";
if(!listen(socket, 0)){
perror("Socket error");
}
//struct timespec delay = {0,33333333}; // 30Hz
struct timespec delay = {0,100000000}; // 100Hz
int running = 1;
int ret = 0;
while(running){
ret = recvfrom(socket, &buffer, 100, 0, NULL, NULL);
if (ret < 0){
perror("Socket error");
} else if (ret > 0){
printf("%d: %s\n", ret, buffer);
}
nanosleep(&delay,NULL);
}
}
client.c
#include "common.h"
void main(void){
int socket = createSocket(0);
printf("Started client on port %d\n", socket);
if(!sendData(127,0,0,0,12345, socket, "test!", 5)){
perror("Socket error");
} else {
printf("Sent data.\n");
}
}
【问题讨论】:
-
不要为 UDP 调用
listen。 man listen:“sockfd 参数是一个文件描述符,它引用了 SOCK_STREAM 或 SOCK_SEQPACKET 类型的套接字”。也就是说,listen 只针对 TCP。 -
if(!listen(socket, 0))。那张支票是错的。0表示成功。所以你应该检查-1,你会看到那里出现错误。 -
或许使用 127.0.0.1:howtogeek.com/149227/…
-
也可以考虑使用
inet_aton将字符串“xxx.xxx.xxx.xxx”ipv4地址转换为二进制地址 -
@yano 原来你是对的!还有一个问题把整个事情搞砸了。见答案。