| New Reply |
Cygwin can't receive UDP packet using recvfrom |
Share Thread | Thread Tools |
| Sep20-12, 11:02 PM | #1 |
|
|
Cygwin can't receive UDP packet using recvfrom
Hallo,
I have a "listener" and "talker" program, "listener" to listen an UDP packet sent by "talker". Both work in linux machine (actually I test in same machine, so using localhost as address). I run "listener" in linux and "talker" in windows (via cygwin), it's work fine. However, it doesn't work in opposite, i.e. run "talker" in linux and "listener" in windows (cygwin). Could you help me to find out what is wrong? I have tried to use 0, MSG_PEEK, MSG_WAITALL in recvfrom() argument, all don't work. Here is the code: listener.c Code:
/*
** 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 <netdb.h>
#define MYPORT "4950" // the port users will be connecting to
#define MAXBUFLEN 100
// 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(void)
{
int sockfd;
struct addrinfo hints, *servinfo, *p;
int rv;
int numbytes;
struct sockaddr_storage their_addr;
char buf[MAXBUFLEN];
socklen_t addr_len;
char s[INET6_ADDRSTRLEN];
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, MYPORT, &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;
}
printf("listener: waiting to recvfrom...\n");
addr_len = sizeof their_addr;
if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1 , /*0*/MSG_PEEK,
(struct sockaddr *)&their_addr, &addr_len)) == -1) {
perror("recvfrom");
exit(1);
}
printf("listener: got packet from %s\n",
inet_ntop(their_addr.ss_family,
get_in_addr((struct sockaddr *)&their_addr),
s, sizeof s));
printf("listener: packet is %d bytes long\n", numbytes);
buf[numbytes] = '\0';
printf("listener: packet contains \"%s\"\n", buf);
close(sockfd);
return 0;
}
Code:
/*
** talker.c -- a datagram "client" 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 <netdb.h>
#define SERVERPORT "4950" // the port users will be connecting to
int main(int argc, char *argv[])
{
int sockfd;
struct addrinfo hints, *servinfo, *p;
int rv;
int numbytes;
if (argc != 3) {
fprintf(stderr,"usage: talker hostname message\n");
exit(1);
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
if ((rv = getaddrinfo(argv[1], SERVERPORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and make a socket
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("talker: socket");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "talker: failed to bind socket\n");
return 2;
}
if ((numbytes = sendto(sockfd, argv[2], strlen(argv[2]), 0,
p->ai_addr, p->ai_addrlen)) == -1) {
perror("talker: sendto");
exit(1);
}
freeaddrinfo(servinfo);
printf("talker: sent %d bytes to %s\n", numbytes, argv[1]);
close(sockfd);
return 0;
}
|
| Sep20-12, 11:04 PM | #2 |
|
|
do you have a firewall running on windows? try turning it off during your test.
|
| Sep20-12, 11:06 PM | #3 |
|
|
my Windows Firewall is off.
|
| Sep20-12, 11:37 PM | #4 |
|
|
Cygwin can't receive UDP packet using recvfrom
can you run the listener and talker both on windows in different sessions? this would determine whether the listener can work on windows.
is 4950 port already in use on your windows box? http://www.sans.org/security-resourc...q/oddports.php the website above says it could be used by icq trojan (looks like a virus maybe) so try using different port numbers. |
| Sep21-12, 12:07 AM | #5 |
|
Recognitions:
|
Install wireshark (http://www.wireshark.org/).
Wireshark allows you to make a trace of all packets sent in and out. It comes with a nifty gui that is very intuitive. It's available both on Linux and Windows. |
| Sep21-12, 12:13 AM | #6 |
|
|
Hey ksatria.
One thing you might want to see is if you are using localhost whether there are issues about the TCP/IP stack for cygwin/windows communication regarding networking. To test this, you should try the following: connect to an actual IP address (not localhost) or try using two individual machines with one being a listener and another being a talker, or (if you can do this), route your packets outside of your machine and back again. A better suggestion is if you have a router, to use the router to force data to be resolved outside your own machine. The point of doing this is that any kind of network packet monitoring program including a firewall will pick up activity on a particular port and that means that if you get any activity, it's not the programs. Also try using a custom port (something with a high number) since many standard services use low ports (even as high as the thousands up to 8000 in some cases). |
| Sep21-12, 01:53 AM | #7 |
|
|
thanks for all the responses.
@jedishrfu hmm, even in same Windows, they can't communicate. I run "listener" in one Cygwin terminal, and run "talker" in another Cygwin terminal and issue these command: $ ./talker 1x.15x.7x.154 "hello cygwin" or by using $ ./talker 127.0.0.1 "hello cygwin" still the listener keep waiting. I also try to change port number to "4960" (seem nobody using), also doesn't work. @I like Serena Yes, the packet is received, I can see it from Wireshark; linux run "talker", windows (cygwin) run "listener". Code:
0000 6x 3x 5x 8x 4x fx 3y ey ay 0y 1y 2y 08 00 45 00 0010 00 29 00 00 40 00 3e 11 ca 70 1x bx 0x 6x 1y 9y .)..@.>. .p...g.. 0020 4y 9y bf e7 13 60 00 15 ad f0 68 65 6c 6c 6f 20 O....`.. ..hello 0030 77 69 6e 64 6f 77 73 00 00 00 00 00 windows. .... @chiro I tried using higher port, 8666, also doesn't work, and actual IP address as well (see above). Using 2 machine (1 windows, 1 linux), only linux as listener and windows (cygwin) as talker that work, opposite doesn't work. some research in various website say there is problem with recvfrom with MGS_WAITALL, but I'm not using it. hmmm...... ??? |
| Sep21-12, 03:59 AM | #8 |
|
|
ksatria: can you do both a listen and talk in windows?
|
| Sep21-12, 04:05 AM | #9 |
|
|
@chiro:
no, I can't. only these scenario work: 1. linux to linux, (same machine via 127.0.0.1) 2. windows to linux but not : 1. linux to windows, nor 2. windows to windows so the problem is in windows (using cygwin) side when receiving. (the code in linux and windows are exactly the same). from Wireshark I see the packet sent from linux machine is received in windows machine, but somehow the "listener" can't catch it. |
| Sep21-12, 04:16 AM | #10 |
|
|
Sounds like some kind of Winsock issue.
Have you tried using a platform specific ifdefs to load the Winsock library and then use the standard commands but calling them through the Winsock API rather than the standard? I'm not sure, but my guess is that all your code is wrapped around Winsock anyway for the windows implementation (which you don't see unless you dig deeper). So another option for you is to look at what's going on for the windows specific code and see how its configuring Winsock (since if it's configuring it wrong, then things are going to screw up). |
| Sep21-12, 05:06 AM | #11 |
|
|
actually I'm not use winsock, I use sys/socket.h from linux, as I use cygwin.
then, I try to make the "windows version" here the code, not much different
Spoiler
Code:
/*
** listener.c -- a datagram sockets "server" demo
*/
#include <stdio.h>
//#include <WinSock.h>
#include <WinSock2.h>
#include <Windows.h>
#include <ws2tcpip.h>
#define MYPORT "4960"//"4950" // the port users will be connecting to
#define MAXBUFLEN 100
// 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(void)
{
int sockfd;
struct addrinfo hints, *servinfo, *p;
int rv;
int numbytes;
struct sockaddr_storage their_addr;
char buf[MAXBUFLEN];
socklen_t addr_len;
char s[INET6_ADDRSTRLEN];
WSADATA wsaData; // if this doesn't work
//WSAData wsaData; // then try this instead
// MAKEWORD(1,1) for Winsock 1.1, MAKEWORD(2,0) for Winsock 2.0:
if (WSAStartup(/*MAKEWORD(1,1)*/MAKEWORD(2,0), &wsaData) != 0) {
fprintf(stderr, "WSAStartup failed.\n");
exit(1);
}
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, MYPORT, &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) {
closesocket(sockfd);//close(sockfd);
perror("listener: bind");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "listener: failed to bind socket\n");
return 2;
}
printf("listener: waiting to recvfrom...\n");
addr_len = sizeof their_addr;
if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1 , 0,
(struct sockaddr *)&their_addr, &addr_len)) == -1) {
perror("recvfrom");
exit(1);
}
printf("listener: got packet from %s\n",
inet_ntop(their_addr.ss_family,
get_in_addr((struct sockaddr *)&their_addr),
s, sizeof s));
printf("listener: packet is %d bytes long\n", numbytes);
buf[numbytes] = '\0';
printf("listener: packet contains \"%s\"\n", buf);
closesocket(sockfd);//close(sockfd);
return 0;
}
then I able to do Windows (winsock) to Windows (cygwin) successfully, but still can't receive from linux. |
| Sep21-12, 06:33 AM | #12 |
|
|
One suggestion is to require a later version of WinSock: the older version 1.1 had a few problems and you'll always have 2.0 on any standard Windows OS (even 2000 and above).
I just looked up some old code I wrote a very long time ago, and I have some comments. The first one is that you should make sure the socket family is set to the TCP/IP family so that it knows that you are using the UDP protocol (since you have specified SOCK_DGRAM). Also if you are passing a port you need to make sure you use the htons() function for servers and the htonl function as well (for setting up listening parameters). You need to also setup the servers and clients in a unique way: clients usually take the address as htonl(INADDR_ANY) but servers take a specific IP address in the data structure. The way I did it ages ago doesn't look like the way you did it, but the first thing I would do is force the family to AF_INET and also force the socket type to TCP/IP to start off with. |
| Sep21-12, 08:08 AM | #13 |
|
Recognitions:
|
On windows you need to use the winsock library.
In particular it needs to be initialized with WSAStartup(). Otherwise it will only partially work without warnings. See for instance http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx for an example (at the bottom of the page). |
| Sep21-12, 08:14 AM | #14 |
|
|
Yeah, what I Like Serena said is kind of important.
|
| New Reply |
| Thread Tools | |
Similar Threads for: Cygwin can't receive UDP packet using recvfrom
|
||||
| Thread | Forum | Replies | ||
| cygwin + g95 | Computers | 1 | ||
| Cygwin, why does my lab recommend to NOT use it? | Math & Science Software | 15 | ||
| Cygwin specific package to installl SSH | Computing & Technology | 2 | ||
| Cygwin | Computing & Technology | 1 | ||
| Cygwin and Radware | General Physics | 0 | ||