Je vais d'abord vous donner l'objectif du code. C'est un udpserver et est censé fournir des statistiques sur le nombre de paquets reçus et le temps pris etc. Le code client fait partie du code embarqué de l'entreprise et ne peut pas être partagé. Voici le code.Code de programmation de socket Exécute sous XP mais échoue sur Windows 7
/*
** 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;
}
Maintenant pour l'environnement en cours d'exécution.
J'ai exécuté le code ci-dessus sur Windows XP après l'avoir compilé en utilisant Cygwin pour générer un fichier .exe. Cela fonctionne parfaitement bien là-bas. Cependant quand je compilé sur un ordinateur Windows 7 machine (à nouveau en utilisant Cygwin (fichier setup_X86.exe BTW) il compile très bien mais en l'exécutant débogage montre qu'il n'atteint que le journal de débogage
"printf("listener: waiting to recvfrom...\n");
sur la ligne 191.
J'ai essayé exécuter l'exécutable en utilisant la compatibilité XP SP3 et privilèges d'administrateur. J'ai essayé de regarder en ligne mais je trouve pas de solution. Est-ce que quelqu'un sait si je l'ai fait une erreur lors de la compilation? j'ai fait simple
gcc -o udpserver.exe udpserver.c
et c'était réussi. S'il vous plaît laissez-moi savoir ce que je peux faire pour affiner le problème. Je suis encore relativement nouveau dans la programmation et la programmation de sockets en général.
Merci d'avance!
Le client s'exécute-t-il sur le même ordinateur ou sur le réseau? Si le client est sur le réseau, vous souvenez-vous de configurer le pare-feu? –
Désolé, il m'a fallu un certain temps pour répondre. J'ai été retiré hier pour d'autres travaux. J'ai essayé de désactiver le pare-feu aujourd'hui. Même problème. –
Je vois que vous vous engagez seulement à la première adresse/protocole que vous trouvez; peut-être vous lier à IPv6 lorsque le client attend IPv4, ou peut-être que vous liez à la mauvaise adresse, par exemple, 127.0.0.1 ou l'un des adaptateurs de tunnel? Vous pouvez utiliser 'netstat -a -n -b' pour vérifier la liaison ou ajouter les diagnostics appropriés à votre code. –