Reputation: 121
I am having a server socket that listens for timeout for read using setsockopt. the server waits for sometime on connect and after some time accepts connection from "accepted connection from 00:00:00:00:00:00". how to solve this issue. Pasted the server code. I am not running the client code while I am getting this error.
void * serverMainThread(void* arg)
{
struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
char buf[1024] = { 0 };
char*tokenCommand,*tokenValue;
int s, client, bytes_read, bytes_written, count = 0, distance;
socklen_t opt = sizeof(rem_addr);
struct timeval tv;
int socketflag=true, loopflag=true;
// allocate socket
s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
if(s<0)perror("socket call error");
// bind socket to port 1 of the first available
// local bluetooth adapter
loc_addr.rc_family = AF_BLUETOOTH;
loc_addr.rc_bdaddr = *BDADDR_ANY;
loc_addr.rc_channel = (uint8_t) 1;
int b = bind(s, (struct sockaddr *)&loc_addr, sizeof(loc_addr));
if(b<0) perror("error in bind");
// put socket into listening mode
int l = listen(s, 1);
if(l<0)perror("error in listen");
tv.tv_sec = 65; // 30 seconds
tv.tv_usec = 0; // microsecs, set to 0 (or ...)
setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv,sizeof(struct timeval));
while(true)
{
printf("for new process->socket count = %d", count);
sleep(10);
// accept one connection
client = accept(s, (struct sockaddr *)&rem_addr, &opt);
printf("enter a number to continue\n");
scanf("%d",&distance);
if(client<0) perror("server thread accept");
int forkRet = fork();
loopflag= socketflag = true;
if(forkRet >= 0)
{
if(forkRet == 0)//child thread
{
childPid = getpid();
printf("pid of new child created =%d\n",(int)childPid);
ba2str( &rem_addr.rc_bdaddr, buf );
fprintf(stderr, "accepted connection from %s\n", buf);
printf("enter a number to continue\n");
scanf("%d",&distance);
memset(buf, 0, sizeof(buf));
while(socketflag)
{
// read data from the client
printf("\nbefore read\n");
bytes_read = read(client, buf, sizeof(buf));
if(bytes_read>=0) buf[bytes_read] ='\0';
printf("%d bytes read\n",bytes_read);
if(bytes_read> 0)
{
loopflag = false;
printf("\npid of current =%d\n",(int)childPid);
distance = findDistance(buf);
if(distance >= 10)
{
ringAlarm();
strcpy(buf,"Ring");
bytes_written = write(client, buf , strlen(buf));
}
else
{
bytes_written = write(client, "No Ring" , 8);
}
}
else
{
if(!loopflag)
{
printf("as loop flag is false, make socketflag false");
socketflag = false;
}
}
}
close(client);
close(s);
printf("\n child process exit\n");
exit(0);
}
else//parent
{
wait(0);
close(client);
// close(s);
printf("\n parent exit\n");
}
}
}
// close connection
//close(client);
//close(s);
}
Upvotes: 0
Views: 277
Reputation: 98486
The problem is that you are not checking the error from accept()
. You should write something like:
client = accept(s, (struct sockaddr *)&rem_addr, &opt);
if (client < 0)
perror("error in accept");
(BTW, you should return or abort or something afer detecting these errors, continuing as if it didn't happen will have bad consequences.)
If you run the program this way you'll get:
error in accept: Resource temporarily unavailable
That correspond to a EAGAIN
code, that is a not-so-well-documented error code for timeout. Which is expected, because you set SO_RCVTIMEO
on the listening socket! The all-zeroes address happens because you are not acually getting a connection, so the sockaddr
structure is left zero-initialized.
You have several options:
SO_RCVTIMEO
from the listening socket, and add it to the client
socket, if needed.EAGAIN
error in accept()
and loop.EAGAIN
error in accept()
(or any other error code) and return to the caller.Upvotes: 3