Cygwin can't receive UDP packet using recvfrom

  • Thread starter ksatria
  • Start date
In summary, the conversation is about a problem with a "listener" and "talker" program that communicate through UDP packets. The programs work fine when run on a Linux machine and a Windows machine (via cygwin), but do not work when run on the same machine with localhost as the address. The conversation suggests trying to run the programs on different machines or using a different port number to see if the issue lies with the TCP/IP stack. Other suggestions include using a packet monitoring program like Wireshark and trying to run the programs with different settings.
  • #1
ksatria
16
0
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;
}

talker.c
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;
}

both are the example program from http://beej.us/guide/bgnet/output/html/multipage/clientserver.html#simpleclient.
 
Computer science news on Phys.org
  • #2
do you have a firewall running on windows? try turning it off during your test.
 
  • #3
my Windows Firewall is off.
 
  • #4
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-resources/idfaq/oddports.php

the website above says it could be used by icq trojan (looks like a virus maybe)

so try using different port numbers.
 
  • #5
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.
 
  • #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).
 
  • #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. ...
hm, is it cygwin problem?

@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... ?
 
  • #8
ksatria: can you do both a listen and talk in windows?
 
  • #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.
 
  • #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).
 
  • #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

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.
 
  • #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.
 
  • #14
Yeah, what I Like Serena said is kind of important.
 

What is Cygwin?

Cygwin is a free and open-source software development environment that allows developers to run Unix-like operating systems on Windows computers.

Why can't Cygwin receive UDP packets using recvfrom?

There are a few possible reasons for this issue. One possibility is that the firewall on your computer is blocking the UDP packets. Another possibility is that your network configuration is incorrect or incompatible with Cygwin. It's also possible that there is a bug in the Cygwin software itself.

How can I fix the issue of not being able to receive UDP packets in Cygwin?

The first step is to check your firewall settings and make sure that UDP traffic is allowed. If that doesn't solve the issue, you may need to troubleshoot your network configuration or try updating your version of Cygwin. If you suspect a bug in the software, you can report it to the Cygwin community for further assistance.

Can I use a different function instead of recvfrom to receive UDP packets in Cygwin?

Yes, there are alternative functions that can be used for receiving UDP packets in Cygwin, such as recvmsg or recv. However, it's important to note that these functions may have different parameters and return values compared to recvfrom, so they may require some modifications to your code.

Is Cygwin the only option for running Unix-like environments on Windows?

No, there are other options such as Windows Subsystem for Linux (WSL) and virtual machines that can also be used to run Unix-like environments on Windows. Each option has its own advantages and limitations, so it's best to research and choose the one that best fits your needs.

Similar threads

  • General Math
Replies
2
Views
9K
  • Engineering and Comp Sci Homework Help
Replies
8
Views
2K
  • Engineering and Comp Sci Homework Help
Replies
3
Views
4K
  • Programming and Computer Science
Replies
4
Views
3K
Back
Top