【发布时间】:2015-12-28 20:38:34
【问题描述】:
首先让我告诉你代码的目标。 它是一个 udpserver,应该提供接收到的数据包数量和所用时间等的统计信息。客户端代码是公司嵌入代码的一部分,不能共享。下面是代码。
/*
** listener.c -- a datagram sockets "server" demo
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <netdb.h>
#include <time.h>
#include <math.h>
#include "windows.h"
#define MYPORT "4950" // Default port number users will be connecting to
#define MAXBUFLEN 1497
#define TIMEOUT_PERIOD_IN_SEC 5 /* Time out after the last packet reception */
//#define DEBUG_ENABLE
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
int main(int argc, char *argv[])
{
int sockfd;
struct addrinfo hints, *servinfo, *p;
int rv;
int numbytes=0;
struct sockaddr_storage their_addr;
char buf[MAXBUFLEN];
socklen_t addr_len;
char s[INET6_ADDRSTRLEN];
int flag=1;
struct timeval tv;
fd_set rfds;
int retval;
long long length = 0;
double totalTxBits=0;
double dataRate=0;
FILETIME sysTime;
long long startTime=0;
long long endTime=0;
long long timeDurationInMicSec;
long total_no_of_packets=0;
long expected_length=0;
char portNum[8];
int i;
switch(argc)
{
case 2:
{
strncpy(portNum, argv[1],8);
if((0==strcmp(portNum,"-h")) || (0==strcmp(portNum,"h")))
{
printf("\r\nUsage: \r\n\t udpserver.exe [<port num>] [<expected length(bytes)>]\r\n");
printf("\r\nNote: All parameters are optional\r\n");
printf("\r\nExample: \r\n\t i) udpserver.exe \r\n");
printf("\n\t ii) udpserver.exe 8000 \r\n");
printf("\n\t iii) udpserver.exe 8000 100000\r\n");
printf("\n\t iv) udpserver.exe 8000 100000 1400\r\n");
return 1;
}
// Make sure that argument contains nothing but digits
for (i = 0; i < strlen(portNum); i++)
{
if (!isdigit(portNum[i]))
{
printf("\r\n Invalid port number \r\n");
printf("\r\nUsage: \r\n\t udpserver.exe [<port num>] [<expected length>]\r\n");
return 1;
}
}
}
break;
case 3:
{
strncpy(portNum, argv[1],8);
/* Make sure that argument contains nothing but digits */
for (i = 0; i < strlen(portNum); i++)
{
if (!isdigit(portNum[i]))
{
printf("\r\n Invalid port number \r\n");
return 1;
}
}
printf("\r\nExpected length :%d \r\n",atoi(argv[2]));
expected_length = atoi(argv[2]);
}
break;
case 4:
{
strncpy(portNum, argv[1],8);
/* Make sure that argument contains nothing but digits */
for (i = 0; i < strlen(portNum); i++)
{
if (!isdigit(portNum[i]))
{
printf("\r\n Invalid port number \r\n");
return 1;
}
}
expected_length = atoi(argv[2]);
expected_length = expected_length * atoi(argv[3]);
printf("\r\nExpected length :%d (%d x %d)\r\n",expected_length,atoi(argv[2]),atoi(argv[3]));
}
break;
default:
{
strcpy(portNum, MYPORT);
expected_length=0;
}
break;
}
printf("\r\nWaiting on port number :%s \r\n",portNum);
tv.tv_sec = TIMEOUT_PERIOD_IN_SEC; /* Time out after the last packet reception */
tv.tv_usec = 0;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE; // use my IP
if ((rv = getaddrinfo(NULL, portNum, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and bind to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("listener: socket");
continue;
}
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("listener: bind");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "listener: failed to bind socket\n");
return 2;
}
freeaddrinfo(servinfo);
total_no_of_packets=0;
while(flag)
{
#ifdef DEBUG_ENABLE
printf("listener: waiting to recvfrom...\n");
#endif /* DEBUG_ENABLE */
addr_len = sizeof their_addr;
if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1 , 0,
(struct sockaddr *)&their_addr, &addr_len)) == -1)
{
perror("recvfrom");
exit(1);
}
total_no_of_packets++;
#ifdef DEBUG_ENABLE
printf("listener: got packet from %s\n",
inet_ntop(their_addr.ss_family,
get_in_addr((struct sockaddr *)&their_addr),
s, sizeof s));
#endif /* DEBUG_ENABLE */
if (0==length)
{
GetSystemTimeAsFileTime(&sysTime);
startTime = sysTime.dwHighDateTime;
startTime = (startTime<<32) | sysTime.dwLowDateTime; /* number of 100-nanosecond intervals */
}
#ifdef DEBUG_ENABLE
printf("listener: packet is %d bytes long\n", numbytes);
#endif /* DEBUG_ENABLE */
length+=numbytes;
#if 0
GetSystemTimeAsFileTime(&sysTime);
endTime =sysTime.dwHighDateTime;
endTime = (endTime<<32) | sysTime.dwLowDateTime; /* number of 100-nanosecond intervals */
#endif
buf[numbytes] = '\0';
#ifdef DEBUG_ENABLE
printf("listener: packet contains \"%s\"\n", buf);
#endif /* DEBUG_ENABLE */
FD_ZERO(&rfds);
FD_SET(sockfd, &rfds);
retval = select(sockfd+1, &rfds, NULL, NULL, &tv);
if (retval == 0)
{
GetSystemTimeAsFileTime(&sysTime);
endTime =sysTime.dwHighDateTime;
endTime = (endTime<<32) | sysTime.dwLowDateTime; /* number of 100-nanosecond intervals */
timeDurationInMicSec =(endTime - startTime) / (long long)10;
/* Subtract the last time-out value */
if(timeDurationInMicSec)
{
timeDurationInMicSec -= ((long long)(TIMEOUT_PERIOD_IN_SEC *1000*1000));
}
printf("\r\n$Time taken :%ld micro sec\r\n",timeDurationInMicSec);
/* Convert to bits */
totalTxBits = length*8;
if(timeDurationInMicSec)
{
dataRate = (totalTxBits*1000*1000)/timeDurationInMicSec;
}
if(dataRate)
{
printf("$Number of packets recieved :%lld\r\n",(total_no_of_packets));
printf("$Total number of bytes recieved :%lld\r\n",(length));
printf("\r\n$DataRate :%f bits per sec\n",dataRate);
printf("\r\n$DataRate :%f kbps (kilo bits per sec)\n",(dataRate/1024));
printf("\r\nNet throughput :%f mbps (mega bits per sec)\n",(dataRate/(1024*1024)));
if(0 != expected_length)
{
if(expected_length >= length)
{
printf("\r\nData loss :%lld bytes ( %f percentage)",(expected_length - length), ((float)((expected_length - length)*100))/(float)expected_length);
}
}
}
else
{
printf("$Error: Unable to calculate throughput.");
}
break;
}
}
close(sockfd);
return 0;
}
现在是运行环境。
在使用 Cygwin 编译后,我在 Windows XP 上运行上述代码以生成 .exe 文件。它在那里工作得很好。 但是,当我在 Windows 7 机器上编译它时(再次使用 cygwin(setup_X86.exe 文件 btw)它编译得非常好,但是在执行它时调试显示它只到达调试日志
"printf("listener: waiting to recvfrom...\n");
在第 191 行。
我尝试使用 XP SP3 兼容性和管理员权限运行可执行文件。我试图在网上查找,但没有找到解决方案。有谁知道我在编译过程中是否犯了错误?我做了一个简单的
gcc -o udpserver.exe udpserver.c
它成功了。请让我知道我可以做些什么来进一步缩小问题的范围。我对套接字编程和一般编程还是很陌生。
提前致谢!
【问题讨论】:
-
客户端是在同一台机器上运行,还是在网络上运行?如果客户端在网络上,你记得配置防火墙吗?
-
抱歉,我花了一段时间才回复。我昨天因其他工作被拉走。我今天尝试禁用防火墙。同样的问题。
-
我看到你只绑定到你找到的第一个地址/协议;也许您在客户端期待 IPv4 时绑定到 IPv6,或者您绑定到错误的地址,例如 127.0.0.1 或隧道适配器之一?您可以使用
netstat -a -n -b来检查绑定,或将适当的诊断信息添加到您的代码中。 -
你完全正确。 Netstat 确实揭示了这个问题。我不知道我为什么使用 AF_UNSPEC 系列。我只是将其更改为 AF_INET 并且它有效。显然,Windows 7 优先于 ipv6 而不是 ipv4。谢谢一堆。如果您对此做出回答,我会将其标记为已接受。
标签: c sockets windows-7 cygwin windows-xp