C server client program "Cannot bind socket" after being run 10 :: 8 posts - 4 authors - Last post: Feb 23C server client program "Cannot bind socket" after being run 10 times Programming int main(int argc, char** argv) { char data[1024]; http://ubuntuforums.org/showthread.php?t=704600HOME | Hi all,
First off, this board is awesome so thanks to anyone and everyone who
takes the time to read my novel. :)
I wrote the below code. All I'm trying to do is read from PASSTHRU or INST,
and pass data from one to the other. port[INST] is already up and running,
as is port[PASSTHRU], however port[PASSTHRU].clientSocket is only set when
I get accept() from port[PASSTHRU].
I can telnet to my server port fine, but if my server sends data from PASSTHRU
to INST, it sends something like
Afg67 Cre.+ c
but telnet only gets something like this
fg67 Cr+c
so some characters are missing. If I print the hex values RIGHT BEFORE I SENT
it to the PASSTHRU.clientSocket socket, everything looks okay.
I believe I set-up my serial device properly (INST) and my server ip port
properly (PASSTHRU), however maybe not since I'm new to this. However since
sometimes chars from telnet to server are repeated and some are missing in
the other direction, maybe I didn't set up my ip port (PASSTHRU) or my serial
port (INST) properly, and some sort of control chars are being intermixed?
How I configured the serial port (INST) is below. The ip socket (PASSTHRU)
is very standard (socket using AP_INET, SOCK_STREAM, IPPROTO_TCP...). Since
some chars seem missing on returning to the clientSocket (telnet as a test),
I tried to turn off every blocking or delay feature...
clientSocket is init to -1, which is why I check that value to see if this is
the first time it's connected.
Part of the problem is I know sleep(1) helps a lot, but I'm not allowed to do
that. I need a proprietary close-sourced application to connect to my
PASSTHRU socket and not even know I'm there! Thus, any artificial delays are
bad. I can fiddle with artificial delays but there must be a better way...
Anyway, here is the code I think is relevant. Any help is greatly appreciated,
as I've been fiddling with this all day and I'm getting very discouraged. I'm
using RH 7.x with the 2.4.18-14 kernel is it matters.
Thanks so much in advance.
Josh
/* this will tell start_listening whether clientSocket
exists on PASSTHRU socket */
volatile sig_atomic_t passthruActive = 0;
start_listening(...)
unsigned int passthruClientLen;
int maxfd = (port[REMORA].fd) + 1;
int i, a, k, p;
char input;
int select_value;
char head[4096];
char tempbuf[4096];
int num_bytes;
fd_set watchset;
struct timeval loopdelay;
FILE* comm_file;
...
/* all sockets are open, confirmed via netstat -l and can telnet no problem... */
while (TRUE)
{
strcpy(tempbuf, "");
strcpy(head, "");
.
.
.
loopdelay.tv_sec = 0; //SELECTDELAY;
loopdelay.tv_usec = 0; /* must reset this for each call - select diddles it */
FD_ZERO(&watchset); /* clear all bits in this set */
FD_SET(port[INST].fd, &watchset); /* watch our data instrument */
FD_SET(port[PASSTHRU].fd, &watchset); /* watch the passthru */
if ((select_value = select(maxfd, &watchset, NULL, NULL, &loopdelay)) > 0)
{
if (FD_ISSET(port[PASSTHRU].fd, &watchset))
{
/* we received something from our passthru */
/* this should only happen upon the first connection */
/* first set our flag that passthru has priority until released */
passthruActive = 1;
if (port[PASSTHRU].clientSocket == -1)
{
/* this is our first client connection */
/* Set the size of the in-out parameter */
passthruClientLen = sizeof(port[PASSTHRU].clientAddress);
/* we've received data from the passthru port */
if ((port[PASSTHRU].clientSocket = accept(port[PASSTHRU].fd,
(struct sockaddr *) &port[PASSTHRU].clientAddress,
&passthruClientLen)) < 0)
{
;//logger(logfile, "ERROR -- 9 We could not accept the call from the passthru socket");
} /* end if accept... */
else
{
/* now that we've accepted the connection, listen */
FD_SET(port[PASSTHRU].clientSocket, &watchset);
/* must increase maxfd to listen to new client socket */
if (port[PASSTHRU].clientSocket >= maxfd)
{
maxfd = port[PASSTHRU].clientSocket + 1;
} /* end if */
/* now read from new client socket */
num_bytes = read(port[PASSTHRU].clientSocket, head, port[PASSTHRU].size - (port[PASSTHRU].buf_idx + 1));
if (num_bytes > 0)
{
strncpy(tempbuf, head, num_bytes);
tempbuf[num_bytes] = 0x00; //add NULL
//tempbuf is only so I can printf for debugging, actuallly send head
send_passthru_data_to_modem(head, port[INST].fd);
} /* end if */
else
{
/* we couldn't find any data on client socket?? */
;
} /* end else */
} /* end else we could accept() */
} /* end if clientSocket == -1 */
else
{
/* we've been here before, client is waiting... */
/* now read from new client socket */
num_bytes = read(port[PASSTHRU].clientSocket, head, port[PASSTHRU].size - (port[PASSTHRU].buf_idx + 1));
if (num_bytes > 0)
{
strncpy(tempbuf, head, num_bytes);
tempbuf[num_bytes] = 0x00; //add NULL
//tempbuf is only for debugging via printf....actually send head
/* our client socket was previously established */
send_passthru_data_to_modem(head, port[INST].fd);
} /* end if */
} /* end else */
} /* end if PASSTHRU */
if (FD_ISSET(port[INST].fd, &watchset))
{
/* we're told something is waiting from the data device */
num_bytes = read(port[INST].fd, head, port[INST].size - (port[INST].buf_idx - 1));
/* see if we have any data to read */
if (num_bytes > 0)
{
strncpy(tempbuf, head, num_bytes);
tempbuf[num_bytes] = 0x00; //add NULL
/* test to see if must transfer the data untouched, or we can modify it */
if (passthruActive == 1)
{
/* passthru is active, so just send whatever modem sent us */
/* back out thru passthru */
for (a = 0; a < strlen(tempbuf); a++)
{
printf("[%i]:%i ", a, tempbuf[a]);
}
printf(" TO PASTHRU:n%sn", tempbuf);
//tempbuf looks good dangit!! send head, which should be just like tempbuf wo/NULL
send_modem_data_to_passthru(head, port[PASSTHRU].clientSocket);
} /* end if passthruActive */
else if (passthruActive == 0)
{
/* write the data we received to our traffic file */
;
} /* end else if passthruActive == 0 */
else
{
/* passthruActive is neither 0 nor 1, which should never happen!! */
;
} /* end else */
} /* end if num_bytes > 0 */
} /* end if FD_ISSET [INST] */
} /* end if select */
} /* end while loop */
} /* end init_data_device() loop */
else
{
logger(logfile, "ERROR -- 8 We could not initialize our data device");
return (FALSE);
} /* end else if data device returned FALSE */
return (TRUE);
} /* end listening(...) */
int send_passthru_data_to_modem(char *input_buffer, int modem_fd)
{
tcdrain(modem_fd);
/* take everything we got from the passthru socket and give it to modem */
return (write(modem_fd, input_buffer, sizeof(input_buffer)));
} /* end send_passthru_data_to_modem(...) */
int send_modem_data_to_passthru(char *input_buffer, int passthruSocket)
{
tcdrain(psthruSocket);
return (write(passthruSocket, input_buffer, sizeof(input_buffer)));
} /* end send_modem_data_to_passthru(...) */
/ **************************************************
Procedure: open_client_serial_port(...)
Purpose: Attempts to open the serial port passed-in as parameter 'port'
Returns: int: 1 if the serial device could not be opened
Notes: This might also 'exit' and not just 'return' if we could not open our
serial device!
**************************************************/
int open_client_serial_port(comm_data_t* port,
const comm_connection_t* environment,
FILE* logfile)
{
int retval = 0; /* our return value */
port->fd = open(port->dev, O_RDWR O_NOCTTY O_NDELAY);
if (port->fd < 0)
{
logger(logfile, "ERROR -- 2 Could not open our serial device");
perror(port->dev);
retval = 1;
port->comm_status = COMM_DOWN;
}
else
{
/* we could open our serial port */
logger(logfile," -- Debug: 2 Successfully opened our serial device");
tcgetattr(port->fd,&port->ser_oldtio); // save the current modem setting so we can restore them
tcgetattr(port->fd,&port->ser_newtio); // save the current modem settings to the new settings structure
cfmakeraw(&port->ser_newtio); // set struct for new term settings to raw. See man 'cfmakeraw'
port->ser_newtio.c_cflag &= ~CRTSCTS; // make sure rts/cts flow control is turned off
port->ser_newtio.c_cflag = (CLOCAL CREAD); // make sure receiver is enabled and port owner not changed
port->ser_newtio.c_iflag &= ~(ISIG IXON IXOFF IXANY);// make sure software flow control is off
cfsetispeed(&port->ser_newtio, B9600); // set the input baudrate for new terminal settings
cfsetospeed(&port->ser_newtio, B9600); // set the output baudrate for new terminal settings
tcgetattr(1,&port->ser_old_stdout_tio); // we gotta do this - there is a Linux bug
tcsetattr(1,TCSANOW,&port->ser_newtio); // make stdout settings like modem settings
tcgetattr(0,&port->ser_oldstdtio); // get stdin settings for restoration ...
tcgetattr(0,&port->ser_newstdtio); // ... and use them as a basis for changes
port->ser_newstdtio.c_lflag &= ~(ICANON ECHO ECHOE ISIG); // make them raw
tcflush(port->fd, TCIOFLUSH); // clear the input and output port buffers
tcsetattr(0,TCSANOW,&port->ser_newstdtio); // set the new attributes immediately
tcsetattr(port->fd,TCSANOW,&port->ser_newtio); // set the new attributes for the serial port immediately
port->comm_status = COMM_OK; //we really need some error checing on all of the above calls ...
}
if (port->fd < 0)
{
logger(logfile, "ERROR -- 2b Could not open our serial device");
perror(port->dev);
exit(-1);
}
//set the serial port to return immediately after a read
fcntl(port->fd, F_SETFL, O_NONBLOCK);
return(retval);
} /* end open_client_serial_port */
Thank you so much! The sizeof is definitely an error, what a dumb mistake. Your reading of my
code is correct with the clientSocket also, however that's because I didn't post my entire code.
What I actually do at the top of the loop, is something like
if (port[PASSTHRU].clientSocket != -1)
{
/* we've got a client so listen to them */
FD_SET(port[PASSTHRU].clientSocket, &watchset);
}
That way once we know someone's there we start looking to see if anything's readable. There's
probably a more elegant way of doing this too, but the sizeof error is most probably the bulk
of my error for now.
Your main problem lies in these two functions:
int send_passthru_data_to_modem(char *input_buffer, int modem_fd)
{
tcdrain(modem_fd);
/* take everything we got from the passthru socket and give it to modem */
return (write(modem_fd, input_buffer, sizeof(input_buffer)));
} /* end send_passthru_data_to_modem(...) */
int send_modem_data_to_passthru(char *input_buffer, int passthruSocket)
{
tcdrain(psthruSocket);
return (write(passthruSocket, input_buffer, sizeof(input_buffer)));
} /* end send_modem_data_to_passthru(...) */
You don't want to use sizeof(input_buffer), there... That will
return whatever your native pointer size is (most likely 4 bytes)...
Because, you're dealing with a char* at this point, not a real
buffer, anymore...
What you need to do is change the functions to take another
arg: the length to send... Then, change your calls to pass in
the length you got from your read()'s... (You could actually
do the sizeof() on the real buffers there, and have it work, but
you don't want to do that... Otherwise, you'd be writing tons of
useless junk that you never actually read into the buffer... You
already know the exact length of the data to send, because you
just read it...)
Also, I think your select() logic is a bit wacky... Namely, you
don't add the "port[PASSTHRU].clientSocket" FD to the fd_set
if it's already been filled in (you've already done an accept()),
which I think you want to... You add it immediately after the
accept(), but then at the top of the loop, you clear out the fd_set,
so that doesn't accomplish anything... You need to add it at
the top of the loop, where you add the other 2 FDs... Also, it
looks like you're only trying to read from that accept()'d
"clientSocket" if your listening socket selects as readable yet
again... (Or, else, I'm just not following the curly braces clearly,
or something...)
How much does getting a small tattoo on your hip/stomach hurt?
Do anyone else have an itchy anus? ?
|