Thread View: borland.public.cppbuilder.internet.socket
4 messages
4 total messages
Started by jer
Wed, 27 Sep 2006 21:24
select returns 10022 invalid argument error
Author: jer
Date: Wed, 27 Sep 2006 21:24
Date: Wed, 27 Sep 2006 21:24
32 lines
2837 bytes
2837 bytes
Hello, I'm a sockets newb looking for some advice from a vet. I'm using Borland BCB6, Windows XP SP2, to write a program to communicate with another computer on a network. I have a thread that sends data out of a UDP socket periodically to the other computer. Before the sendto function I always use select to determine if the socket is writable. I have gotten the software to the point where I am able to send and receive data correctly most of the time. However, intermittently, the select statement times out (I set it to a 3 sec timeout). When this happens I skip the sendto function and try the select again. At this point, select returns SOCKET_ERROR and I get a 10022 error (invalid argument) when I call WSAGetLastError(). From this point on, I use select to check if the socket is writable and each time I get SOCKET_ERROR with 10022. After this happens, I have tried to diagnose what is going on in the PC. I have tried pinging the other computer on the network, and I always get "destination unreachable". Then I tried pinging localhost and I get destination unreachable. If I ping any of the network cards on the PC, even ones unrelated to the socket I'm using, I get destination unreachable. I also cannot disable or enable any of the network cards on the PC. The only way to remedy the situation at this point is to power cycle the PC. Here are my questions: 1. Why would select suddenly timeout after working properly for 10 minutes? 2. Why would I get an invalid argument error after successfully using the same select code many times before? 3. What could I be doing to break ping? Why can't I ping localhost? Any hints or help searching for clues would be hugely appreciated. Thanks, Jer
Re: select returns 10022 invalid argument error
Author: Remy Lebeau (TeamB)
Date: Wed, 27 Sep 2006 23:28
Date: Wed, 27 Sep 2006 23:28
60 lines
2850 bytes
2850 bytes
"jer" <jer_bred_guy@yahoo.com> wrote in message
news:1159392295.406227.295400@e3g2000cwe.googlegroups.com...
> Before the sendto function I always use select to determine if the socket
is writable.
That is generally not a good idea. You should just call sendto() by itself,
and let it report an error if it cannot send.
> However, intermittently, the select statement times out (I set it to
> a 3 sec timeout). When this happens I skip the sendto function and try
> the select again. At this point, select returns SOCKET_ERROR and
> I get a 10022 error (invalid argument) when I call WSAGetLastError().
From the select() documentation:
WSAEINVAL
The timeout value is not valid, or all three descriptor parameters were
NULL.
Please show your actual socket code.
> From this point on, I use select to check if the socket is writable and
> each time I get SOCKET_ERROR with 10022.
My guess would be that your socket is no longer valid.
> After this happens, I have tried to diagnose what is going on in
> the PC. I have tried pinging the other computer on the network,
> and I always get "destination unreachable".
You lost your network connection. Try rebooting the machine, and
double-check the network wires.
> Then I tried pinging localhost and I get destination unreachable.
You probably blew up the TCP/IP stack altogether. Pinging the localhost
should never fail when TCP/IP is working properly.
> Why would select suddenly timeout after working properly for 10
> minutes?
Hard to say without seeing your actual code.
> Why would I get an invalid argument error after successfully
> using the same select code many times before?
Because the socket is no longer valid.
> What could I be doing to break ping?
Hard to say without seeing your actual code.
> Why can't I ping localhost?
Because TCP/IP is not working properly anymore.
Gambit
Re: select returns 10022 invalid argument error
Author: jer
Date: Thu, 28 Sep 2006 17:11
Date: Thu, 28 Sep 2006 17:11
209 lines
7629 bytes
7629 bytes
>> Before the sendto function I always use select to determine if the socket
>>is writable.
>That is generally not a good idea. You should just call sendto() by itself,
>and let it report an error if it cannot send.
I'll give this a shot.
>> However, intermittently, the select statement times out (I set it to
>> a 3 sec timeout). When this happens I skip the sendto function and try
>> the select again. At this point, select returns SOCKET_ERROR and
>> I get a 10022 error (invalid argument) when I call WSAGetLastError().
>From the select() documentation:
>WSAEINVAL
>The timeout value is not valid, or all three descriptor parameters were
>NULL.
>Please show your actual socket code.
See below.
>> Then I tried pinging localhost and I get destination unreachable.
>You probably blew up the TCP/IP stack altogether. Pinging the localhost
>should never fail when TCP/IP is working properly.
Yeah, somehow I've managed to hang TCP/IP. I wonder if there's a way to
restart or reset TCP/IP without rebooting windows?
Here's some of my code.
//This is the code I use to set up the socket for sending data
//The parameters that are passed into the function are global,
//and are used in the send thread, see below.
int Start_UDP_Sock_Send(int* sockfd,
struct sockaddr_in* their_addr,
char* ip_addr,
int send_port)
{
struct hostent *he;
WSADATA wsaData;
int error_status = 0;
struct sockaddr_in my_addr;
char host_name[80];
//Begin setting up network socket
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
{
return error_status = -1;
}
//Set the address of the computer you want to send data to
he = gethostbyname(ip_addr);
//SOCK_DGRAM is used to set up a UDP socket
if ((*sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
return error_status = -2;
}
//Next four lines set up network parameters
(*their_addr).sin_family = AF_INET; // host byte order
(*their_addr).sin_port = htons(send_port); // short, network byte
order
(*their_addr).sin_addr = *((struct in_addr *)he->h_addr);
memset(&((*their_addr).sin_zero), '\0', 8); // zero the rest of the
struct
//used to bind to a specific network interface on local pc
my_addr.sin_family = AF_INET; // host byte order
my_addr.sin_port = 0; // short, network byte order
if (strcmp(ip_addr, "10.100.4.200") == 0)
{
my_addr.sin_addr.s_addr = inet_addr("10.100.4.201");
}
else if (strcmp(ip_addr, "10.100.4.201") == 0)
{
my_addr.sin_addr.s_addr = inet_addr("10.100.4.200");
}
else if (strcmp(ip_addr, "localhost") == 0)
{
my_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
}
memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct
if((bind(*sockfd, (struct sockaddr *)&my_addr, sizeof(struct
sockaddr)))==SOCKET_ERROR)
{
return error_status = -3;
}
return error_status;
}
//This function runs in a separate thread. It sends data on
//the socket set up above.
int __fastcall send_thread_function(LPVOID lpParam)
{
int error_value = 0;
char loc_send_buf[1024];
memset(loc_send_buf, 0, 1024);
//Variables for sleep timer resolution
TIMECAPS tc;
timeGetDevCaps(&tc, sizeof(TIMECAPS));
//Set the resolution of the timer
timeBeginPeriod(tc.wPeriodMin);
int send_cnt = 0;
//used for storing the pc time
struct time pc_time;
fd_set writefds;
struct timeval tv;
int sel_value = 0;
// wait until either socket is ready to send or time out in 3
seconds
tv.tv_sec = 3;
tv.tv_usec = 0;
FD_ZERO(&writefds);
FD_SET(sockfd_send, &writefds);
FILE* test_fptr;
//write debug data to a text file
test_fptr = fopen("C:\\send_log.log", "a+t");
int error_code = 0;
gettime(&pc_time);
if (test_fptr != NULL)
{
//write data
fprintf(test_fptr, "Started Send Thread ***** at: ");
fprintf(test_fptr, "%02d:%02d:%02d:%d\n", pc_time.ti_hour,
pc_time.ti_min, pc_time.ti_sec, pc_time.ti_hund);
fclose(test_fptr);
}
//This function runs in a separate thread. It's used to send data
for(;;)
{
memset(loc_send_buf, 0, 1024);
//memcpy send data out of the global buffer
memcpy(loc_send_buf, glob_send_buf, 1024);
//Use select to time out if data is not ready to be sent
sel_value = select(2, NULL, &writefds, NULL, &tv);
if (sel_value == 0)
{
gettime(&pc_time);
//write debug data to a text file
test_fptr = fopen("C:\\send_log.log", "a+t");
if (test_fptr != NULL)
{
//write data
fprintf(test_fptr, "send select time out at: ");
fprintf(test_fptr, "%02d:%02d:%02d:%d\n", pc_time.ti_hour,
pc_time.ti_min, pc_time.ti_sec, pc_time.ti_hund);
fclose(test_fptr);
}
Sleep(3000);
}
else if (sel_value == SOCKET_ERROR)
{
error_code = WSAGetLastError();
gettime(&pc_time);
//write debug data to a text file
test_fptr = fopen("C:\\send_log.log", "a+t");
if (test_fptr != NULL)
{
//write data
fprintf(test_fptr, "select error: %d at: ", error_code);
fprintf(test_fptr, "%02d:%02d:%02d:%d\n", pc_time.ti_hour,
pc_time.ti_min, pc_time.ti_sec, pc_time.ti_hund);
fclose(test_fptr);
}
Sleep(3000);
}
else
{
error_value = sendto(sockfd_send,
loc_send_buf,
616,
0,
(SOCKADDR *)&their_addr_send,
sizeof(their_addr_send));
if (error_value > 0)
{
send_cnt++;
Sleep(5);
}
else
{
Sleep(5000);
}
}
}
return 0;
}
I have code that I use to receive data as well. I can put this code up
if you think it would help. Your first reply has me thinking of a few
things to try out in the mean time. Thanks so much for your help!
Jer
Re: select returns 10022 invalid argument error
Author: Remy Lebeau (TeamB)
Date: Thu, 28 Sep 2006 18:34
Date: Thu, 28 Sep 2006 18:34
72 lines
3688 bytes
3688 bytes
"jer" <jer_bred_guy@yahoo.com> wrote in message
news:1159444802.345644.119460@m7g2000cwm.googlegroups.com...
> Yeah, somehow I've managed to hang TCP/IP. I wonder if there's a
> way to restart or reset TCP/IP without rebooting windows?
Nope.
> This is the code I use to set up the socket for sending data
> The parameters that are passed into the function are global,
> and are used in the send thread, see below.
Are you protecting your globals from multi-threaded access properly?
> if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
Why are you calling WSAStartup() for each new socket? You do not even need
to call it for each individual thread. You should only be calling it once
at program startup.
> //Set the address of the computer you want to send data to
> he = gethostbyname(ip_addr);
You are not checking for errors in resolving the remote computer.
gethostbyname() will return a NULL pointer if it fails.
> (*their_addr).sin_family = AF_INET; // host byte order
> (*their_addr).sin_port = htons(send_port); // short, network byte
> order
> (*their_addr).sin_addr = *((struct in_addr *)he->h_addr);
> memset(&((*their_addr).sin_zero), '\0', 8); // zero the rest of the
> struct
Use the '->' operator instead of the '*' operator:
their_addr->sin_family = AF_INET; // host byte order
their_addr->sin_port = htons(send_port); // short, network byte order
their_addr->sin_addr = *((struct in_addr *)he->h_addr);
memset(their_addr->sin_zero, '\0', 8); // zero the rest of the struct
> if (strcmp(ip_addr, "10.100.4.200") == 0)
> {
> my_addr.sin_addr.s_addr = inet_addr("10.100.4.201");
> }
> else if (strcmp(ip_addr, "10.100.4.201") == 0)
> {
> my_addr.sin_addr.s_addr = inet_addr("10.100.4.200");
> }
That is not a very generic way to handle IPs. Since the calling code
already knows which IP it wants to send to, it should pass in another
parameter to the function to specify the local IP to bind to. Then the
socket code doesn't need these special case operations anymore.
> if((bind(*sockfd, (struct sockaddr *)&my_addr, sizeof(struct
> sockaddr)))==SOCKET_ERROR)
> {
> return error_status = -3;
> }
You are not closing the socket before exiting when an error occurs.
> sel_value = select(2, NULL, &writefds, NULL, &tv);
The first parameter is never used and should be set to 0:
sel_value = select(0, NULL, &writefds, NULL, &tv);
Gambit
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads