Categories: MSDN / DotNet / Java / Scripts / Linux / PHP Ask - La ask - La Answer

SetTimeOut for Winsock2 in C

Hello,

I am using Java for a TCP server, but I want ot make the client in pure C. I am using the winsock2 lib, but I have one big problem. In my program the server and the client should not wait each others. For an exapmle: all basic programs have this cycle:

read socket;
write socket;

But what happence when the client other the server does not have anything to send? Than the read commands just wait. In Java there is a SetTimeOut function. If there is no activity it throws an exeption. Usually it is

read socket;
if there is an exeption -> write

In this case if the server does not sends anything the client will have the oppurtunity to send something without reading anything from the server.

I hope you understand me. What is the analoge function in C? Could you give me an example?

Thanks!
[871 byte] By [vendor.net] at [2007-11-11 8:46:26]
# 1 Re: SetTimeOut for Winsock2 in C
The errors on sockets seem to be globals -- some integer somewhere is popped to the most recent error code and accessed with a "getlasterror" function. (wsagetlasterror?? something like this, names escape me).

To make it not wait, you want to set the socket to "notblocking" at which point the socket will read, nothing there, pass thru ... this is not the default so you must set this socket option. (setsocketopt?) or wsasetsocketopt or something like that.
jonnin at 2007-11-11 21:01:00 >
# 2 Re: SetTimeOut for Winsock2 in C
After I set it, how can I change the state from read socket to write socket?
vendor.net at 2007-11-11 21:02:06 >
# 3 Re: SetTimeOut for Winsock2 in C
You should be able to send or recieve from the same socket. Use sendto & recievefrom functions (udp & tcp might have slightly different names).

You have to make sure all the stuff is set up properly, but I know this is doable as my sockets are all read & write. (I have some very, very simple udp code if you want me to dig it out, its ugly -- cut and pasted from some examples and poked it until it worked).
jonnin at 2007-11-11 21:03:04 >
# 4 Re: SetTimeOut for Winsock2 in C
If you could post the code, it will be great.

My problem is send and recieve at one time, not from the same socket.
Let`s say that the frame is so
socket read
socket write

That means, that the server MUST send something to the client and then to reciece something. I want this to be dynamic. If there is no responce of the client, thant the server sends comething. It is like a chat client. You can send 1,2, unlimited messages, without the other side to responde, but when it needs to responde it can do it.

Something like:
// This is random
read socket
read socket
write socket
read socket

And this is a cycle. Every line is one iteration.
vendor.net at 2007-11-11 21:04:05 >
# 5 Re: SetTimeOut for Winsock2 in C
In most cases, you will be able to view the errors by examining errno, which is a global integer or in a mutithreaded environment, an implicit function call which returns the latest error code of the application.
Danny at 2007-11-11 21:05:09 >
# 6 Re: SetTimeOut for Winsock2 in C
Its going to have to wait. I thought I had this at home but I dont, and its a long weekend and Im outta here. Sorry in advance if im too slow.
jonnin at 2007-11-11 21:06:08 >
# 7 Re: SetTimeOut for Winsock2 in C
From your original post, it sounds like you want the "read" to return even if there is nothing there. This is called a "non blocking read".

long nonblocking = TRUE;
ioctlsocket(Socket, FIONBIO, &nonblocking);

Something like that. You'll find the read call returns immediatley after making your socket non blocking with this call.

See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/ioctlsocket_2.asp for more info.
PeterS2 at 2007-11-11 21:07:08 >
# 8 Re: SetTimeOut for Winsock2 in C
Thanks PeterS2 ! That`s what I am seeking. Now I have to find some examples of using it in C :)
vendor.net at 2007-11-11 21:08:11 >
# 9 Re: SetTimeOut for Winsock2 in C
Fixed smiles

The examples in visual studio 6.0 are in C (or nearly so, its supposedly C++).
Starting with .net microsoft hid the low level examples.

The following class was created from those C examples, which I can no longer find.
It is basically C in the class methods. I wrote it assuming threaded apps but that is not required if you use the nonblocking IO statements provided by Peter. Anyway, this might help you create the C you need, if not throw it away.

//// .h file

/*simple udp and tcp library

This is supposed to be able to perform most udp and tcp functions.
I am not sure how much of tcp works anymore; UDP is working well.

*/

#ifndef jcomm_file
#define jcomm_file

#define WIN32_LEAN_AND_MEAN

typedef int socklen_t;
#include <afxwin.h> //threads
#include <winsock.h> //this one messes up in .net, the other in 6.0 so whatever
//#include <winsock2.h> //the example included this but it causes problems!

typedef float float_data_t[1024]; //you could make this something else, a struct, etc.
const int size_of_datagram = 4096;
//I assume here that a float is 4 bytes ! seems fair as this stuff needs visual studio to compile...
//tc uses send to send from server back to client, udp uses sendto, I did not have a use for this yet.

struct jcomm_t
{
char *host;
unsigned int port;
char data[size_of_datagram];
bool udp; //udp or tcpip?

void jcomm_t::jcomm_client_init(int portnum, char * host_name, bool is_udp);
void jcomm_t::jcomm_client_send(); //example mostly (use sendto instead)

void jcomm_t::jcomm_server_init(int portnum, bool is_udp);
void jcomm_t::jcomm_server_start(); //example do not use
void jcomm_t::jcomm_cleanup(); //?? it may break all sockets not just this one

static bool jcomm_show_error(); //the help text for each code is printed
sockaddr_in server, local, from;

PHOSTENT phostent;
WSADATA WSAData;
SOCKET WinSocket,tcsocket;

unsigned int Addr;
int fromlen;
};
#endif

------ //end .h

//1-31-05 -- borrows heavily from microsoft examples --

#include "udp-tcp.h"
#include <iostream>
using namespace std;

void jcomm_t::jcomm_client_init(int portnum, char * host_name, bool is_udp)//func
{
// Notice that almost nothing in this code is specific to whether we
// are using UDP or TCP. The socket open command is the only place.
// When connect() is called on a udp socket, it does not
// actually establish the connection as a TCP socket
// would. Instead, TCP establishes the remote half of the
// ( LocalIPAddress, LocalPort, RemoteIP, RemotePort) mapping.
// This enables us to use send() and recv() on datagram sockets,
// instead of recvfrom() and sendto() -- making this a generic object
//suited for either tcp or udp transmission

port = portnum;
host = host_name;
udp = is_udp;

WSAStartup(0x202,&WSAData); //X202 is 514 decimal, it is the 'version required' of something or other.

if (isalpha(host[0])) //if its a Name or a number, we can open it either way
{
phostent = gethostbyname(host);
}
else
{
Addr = inet_addr(host);
phostent = gethostbyaddr((char *)&Addr,4,AF_INET);
}

memset(&server,0,sizeof(server));
memcpy(&(server.sin_addr),phostent ->h_addr,phostent ->h_length);
server.sin_family = phostent ->h_addrtype;
server.sin_port = htons(port);


if(udp)
WinSocket = socket(AF_INET,SOCK_DGRAM,0); // Open a socket udp style
else
{
WinSocket = socket(AF_INET,SOCK_STREAM,0); // Open a socket tcp style
}

/*
local.sin_family = AF_INET;
local.sin_addr.s_addr = INADDR_ANY; //inet_addr("204.130.141.139"); //could be set to an ip address
local.sin_port = htons(port);
cout << local.sin_port << endl;

bool val = true;
setsockopt(WinSocket,IPPROTO_IP,SO_REUSEADDR, (char *) &val, sizeof(bool));
bind(WinSocket,(sockaddr*)&local,sizeof(local) );
*/
connect(WinSocket ,(sockaddr*)&server,sizeof(server)) ;

/*
sockaddr getsa;
int namelen;
getsockname (WinSocket,&getsa, &namelen );
int x;
for(x = 0; x < namelen; x++)
printf("%x",getsa.sa_data[x]);
cout << endl;
*/
jcomm_show_error();
}

void jcomm_t::jcomm_client_send()//func
{
send(WinSocket, data, size_of_datagram ,0);
}

void jcomm_t::jcomm_server_init(int portnum, bool is_udp)//func
{
port = portnum;
udp = is_udp;

WSAStartup(0x202,&WSAData);
local.sin_family = AF_INET;
local.sin_addr.s_addr = INADDR_ANY; //could be set to an ip address
local.sin_port = htons(port);
if(udp)
WinSocket= socket(AF_INET, SOCK_DGRAM ,0); //udp
else
WinSocket= socket(AF_INET, SOCK_STREAM,0); //tcp

bind(WinSocket,(sockaddr*)&local,sizeof(local) );
// We cannot listen() on a UDP socket.

fromlen =sizeof(from);

if (!udp)
{
listen(WinSocket,100);
tcsocket = accept(WinSocket,(struct sockaddr*)&from, &fromlen);
inet_ntoa(from.sin_addr),
htons(from.sin_port) ;
/**/
}
else
tcsocket = WinSocket;
}

//the threads should be customized to handle your packets or do what you need
//they are provided as examples / templates !

UINT jcomm_tcpip_thread(LPVOID pointer)//func
{
jcomm_t * pj = (jcomm_t *) pointer;

listen(pj->WinSocket,5);
pj->fromlen =sizeof(pj->from);
pj->tcsocket = accept(pj->WinSocket,(sockaddr*)&(pj->from), &(pj->fromlen));
inet_ntoa(pj->from.sin_addr);
htons(pj->from.sin_port) ;

/*
for(;;)
{
recv(pj->tcsocket,pj->data,size_of_datagram,0 );
//process data here
}
*/
return 0;
}

UINT jcomm_udp_thread(LPVOID pointer)//func
{
jcomm_t * pj = (jcomm_t *) pointer;
for(;;)
{
recvfrom(pj->tcsocket,pj->data,size_of_datagram,0,
(sockaddr *)&(pj->from),&(pj->fromlen));
//process data here
}
return 0;
}

void jcomm_t::jcomm_server_start()//func
{
if(udp)
AfxBeginThread(jcomm_udp_thread, this, THREAD_PRIORITY_LOWEST, 0, 0, NULL);
else
AfxBeginThread(jcomm_tcpip_thread, this, THREAD_PRIORITY_LOWEST, 0, 0, NULL);
}

void jcomm_t::jcomm_cleanup()//func
{
closesocket(WinSocket);
WSACleanup();
}
jonnin at 2007-11-11 21:09:13 >
# 10 Re: SetTimeOut for Winsock2 in C
The show error function made the post too long:

bool jcomm_t::jcomm_show_error()//func
{
int err = WSAGetLastError();
switch(err)
{
case WSAEINTR: cout << "Interrupted system call.\n"; break;
case WSAEBADF: cout << "Bad file number.\n"; break;
//case WSEACCES: cout << "Permission denied.\n"; break; //no longer supported?
case WSAEFAULT: cout << "Bad address.\n"; break;
case WSAEINVAL: cout << "Invalid argument.\n"; break;
case WSAEMFILE: cout << "Too many open files.\n"; break;
//case WSAEWOULDBLOCK: cout << "Operation would block.\n"; break; //annoying non-important msg
case WSAEINPROGRESS: cout << "Operation now in progress. any Windows Sockets API function called while a blocking function is in progress.\n"; break;
case WSAEALREADY: cout << "Operation already in progress.\n"; break;
case WSAENOTSOCK: cout << "Socket operation on nonsocket.\n"; break;
case WSAEDESTADDRREQ: cout << "Destination address required.\n"; break;
case WSAEMSGSIZE: cout << "Message too long.\n"; break;
case WSAEPROTOTYPE: cout << "Protocol wrong type for socket.\n"; break;
case WSAENOPROTOOPT: cout << "Protocol not available.\n"; break;
case WSAEPROTONOSUPPORT: cout << "Protocol not supported.\n"; break;
case WSAESOCKTNOSUPPORT: cout << "Socket type not supported.\n"; break;
case WSAEOPNOTSUPP: cout << "Operation not supported on socket.\n"; break;
case WSAEPFNOSUPPORT: cout << "Protocol family not supported.\n"; break;
case WSAEAFNOSUPPORT: cout << "Address family not supported by protocol family.\n"; break;
case WSAEADDRINUSE: cout << "Address already in use.\n"; break;
case WSAEADDRNOTAVAIL: cout << "Cannot assign requested address.\n"; break;
case WSAENETDOWN: cout << "Network is down. This error may be reported at any Time if the Windows Sockets implementation detects failure.\n"; break;
case WSAENETUNREACH: cout << "Network is unreachable.\n"; break;
case WSAENETRESET: cout << "Network dropped connection on reset.\n"; break;
case WSAECONNABORTED: cout << "Software caused connection abort.\n"; break;

case WSAECONNRESET: return true; break;//cout << "Connection reset by peer.\n"; break; //removed -- handled

case WSAENOBUFS: cout << "No buffer space available.\n"; break;
case WSAEISCONN: cout << "Socket is already connected.\n"; break;
case WSAENOTCONN: cout << "Socket is not connected.\n"; break;
case WSAESHUTDOWN: cout << "Cannot send after socket shutdown.\n"; break;
case WSAETOOMANYREFS: cout << "Too many references: cannot splice.\n"; break;
case WSAETIMEDOUT: cout << "Connection timed out.\n"; break;
case WSAECONNREFUSED: cout << "Connection refused.\n"; break;
case WSAELOOP: cout << "Too many levels of symbolic links.\n"; break;
case WSAENAMETOOLONG: cout << "File Name too long.\n"; break;
case WSAEHOSTDOWN: cout << "Host is down.\n"; break;
case WSAEHOSTUNREACH: cout << "No route to host.\n"; break;
case WSASYSNOTREADY: cout << "Returned by WSAStartup(), indicating that the network subsystem is unusable.\n"; break;
case WSAVERNOTSUPPORTED: cout << "Returned by WSAStartup(), indicating that the Windows Sockets DLL cannot support this application.\n"; break;
case WSANOTINITIALISED: cout << "Winsock not initialized. This message is returned by any function except WSAStartup(), indicating that a successful WSAStartup() has not yet been performed.\n"; break;
case WSAEDISCON: cout << "Disconnect.\n"; break;
case WSAHOST_NOT_FOUND: cout << "Host not found. This message indicates that the key (Name, address, and so on) was not found.\n"; break;
case WSATRY_AGAIN: cout << "Nonauthoritative host not found. This error may suggest that the Name service itself is not functioning.\n"; break;
case WSANO_RECOVERY: cout << "Nonrecoverable error. This error may suggest that the Name service itself is not functioning.\n"; break;
case WSANO_DATA: cout << "Valid Name, no data record of requested type. This error indicates that the key(Name, address, and so on) was not found. \n"; break;
default: ; //cout << "No socket errors\n"; //left blank so the call to this can be left in silently
cout.flush();
}
return false;
}
jonnin at 2007-11-11 21:10:10 >