While porting to linux I've run across .. err .. 'anomalies' in some of the
socket behavior.
1) When I try to send udp packets to the loopback address, every third(!?)
port returns an "connection refused" error.
2) The latest man page I could find for accept() (23 oct 98) states
"The accept function extracts the first connection request on the queue
of pending connections, creates a new socket *with the same properties of s*,
and allocates a new file descriptor for the socket"
... however even if the listen socket has been set to non-blocking, the socket
returned by accept() blocks. (yes the workaround is obvious)
I apologize in advance if these are known problems, glibc bugs, or expected
behavior; I've searched many places for info regarding this and have so far
seen only mention of some 'accept() bug' on blackdown's (java/linux) homepage.
These programs run as expected on Solaris 5.6 and SCO 5.0.4. I would
appreciate any pointers to a more appropriate forum or an explanation of what
I'm doing wrong. Of course I would like (non)confirmations as well..
These programs were tested under rh 6.0 (running 2.2.12 and the stock
2.2.5) and debian (running 2.0.36). I tried 2.3.19 briefly, w/ same results
for 1); 2) gave me EINVAL for accept() on the receive side and the connection
was never established. Perhaps I screwed up my configuration somehow.
Responders please cc: me.
Thanks for your time
Buck
/* udps.c -- demonstrate supposed udp over loopback 'bug' */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#define MYPORTLOW 10000
#define MYPORTHIGH 10015
int main(void)
{
int sd, i, res;
char msg[20] = "hi there!\n";
struct sockaddr_in addr;
if ((sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
perror("socket");
memset((void *) &addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
for (i = MYPORTLOW; i< MYPORTHIGH; i++)
{
fprintf(stderr, "sending to %d\n", i);
addr.sin_port = ntohs(i);
if ((res = sendto(sd, msg, strlen(msg) + 1, /* send \0 */
0, (struct sockaddr *) &addr,
sizeof(struct sockaddr_in))) < 0)
{
fprintf(stderr, "(res was %d) ", res);
perror("sendto");
}
}
return 0;
}
/* tcpr.c -- demonstrate supposed tcp accept() 'bug' */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#define MYPORT 10012
int main(void)
{
int sd, newsock, res;
char msg[20] = "ackackack";
struct sockaddr_in addr, src_addr;
int src_addr_size;
if ((sd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
perror("socket");
memset((void *) &addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
addr.sin_port = ntohs(MYPORT);
/* set to nonblock */
if ((res = fcntl (sd, F_SETFL, O_NONBLOCK)) < 0)
perror("fcntl");
/* bind */
if ((res = bind(sd, (struct sockaddr *) &addr,
sizeof(struct sockaddr_in))) < 0)
perror("bind");
/* listen */
if ((res = listen(sd, 5) < 0))
perror("listen");
/* accept */
while ((newsock = accept(sd, (struct sockaddr *) &src_addr,
&src_addr_size)) < 0)
{
if (errno == EWOULDBLOCK)
{
fprintf(stderr, "no connex accepted.\n");
sleep(1);
}
else
perror("accept");
}
#if 0
if ((res = fcntl (newsock, F_SETFL, O_NONBLOCK)) < 0)
perror("fcntl");
#endif
/* ok we opened a connection. Listen for a message. */
while ((res = recv(newsock, msg, 20, 0)) < 0)
{
if (errno == EWOULDBLOCK)
{
fprintf(stderr, "no message available.\n");
sleep(1);
}
else
perror("recv");
}
printf("message received: %s", msg);
return 0;
}
/* tcps.c -- run this once you have tcpr fired up to make a connex */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#define MYPORT 10012
int main(void)
{
int sd, res;
char msg[20] = "hi there!";
struct sockaddr_in addr;
if ((sd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
perror("socket");
memset((void *) &addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
addr.sin_port = ntohs(MYPORT);
/* connect */
if ((res = connect(sd, (struct sockaddr *) &addr,
sizeof(struct sockaddr_in))) < 0)
perror("connect");
sleep(10);
/* send message. */
if ((res = send(sd, msg, strlen(msg) + 1, 0)) < 0) /* send \0 */
perror("sendto");
return 0;
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/