Solved

Async Winsock Questions

Posted on 2002-04-30
6
599 Views
Last Modified: 2013-12-03
Ok, this is kind of a multipart question...

1) Let's say I limit my connected users to 5 - I have code to send a reject on connections unless there are less then 5 users connected to my program.

Now, let's say I have 100's of people hitting the connection request to the server, efectively so I keep receiving messages FD_ACCEPT messages - what can I do to guarantee my main server loop will get run if I keep getting bombarded with FD_ACCEPTS?

2) Now I know there are times where all the data for a complete packet may not be received (or sent from what I have read)

So, what do I need to do to make a packet work?

Let's say my packet structure is:

char Type (there would be <256 packet types)
int PacketSize
union of multiple sub types...
type 1
char MsgFrm[20]
char Msg[100]
BOOL Private
Type 2
short CommandID
char CommandParameters[50]
Type 4
char LargeMOTD[500]
etc.

Ok, so what kind of a recv function do I need to create to make sure I get the entire packet? I would prefer to use pointers, but as that may make it EXTREMELY difficult, I could use char arrays for my text messages, command parameters and motd messages, etc..


3) Right now, the client and server are both Windows based.  Let's say I moved one or the other to an alternative OS in which I might have to do some data conversion.  I'm not sure how I do this. Do I have to make my packets arrays of int or shorts and do a conversion on everything?  How do I do this??

Pls, any help would be appreciated.  I'm REALLY lost on this part of async winsock programming.  I have my message loop setup, but until I understand/have a proper recv and send to make sure all data is sent/arrives, I really don't know what to do.


Basically, I'm lost in this area of network programming.  I have most of what I need to do figured out, but I am just having trouble with these last few areas.

PLEASE do not show MFC, I am doing this using the Win32API and Winsock

Please do not reference MSDN and say just read here, I already have.  I have also read a variety of articles including the Winsock FAQ as well as the winsock documents at Gamedev.net (some decent network programming docs).  

I need some viable code that I can look at, step thru and understand how it works.
0
Comment
Question by:navigator010897
  • 3
  • 2
6 Comments
 
LVL 1

Accepted Solution

by:
seva earned 200 total points
ID: 6982714
1) i guess you just don't call accept() if your number of connections is 5.

2) you just use recv(fd, &packet, sizeof(packet), ...)
 where packet may be declared as
 struct my_packet_struct packet;

3) for chars there is no conversion needed.
   for shorts you need to use  htons when you send data,
    and ntohs when you receive.
   for ints you use htonl() and ntohl() respectively
   I am not sure about BOOL, you may want to look
   what is the actual type of BOOL.
0
 
LVL 10

Expert Comment

by:makerp
ID: 6982883
1) see above
2)

int recv(char *buffer,int len)
{
 int so_far = 0;
 while(so_far < len)
 {
     res = recv(sock,buffer + so_far,len - so_far,0);
     if(res == SOCKET_ERROR || so_far == 0)
     {      
         return FAILURE;
     }
     so_far += res;
  }
  return so_far;
}

the call it

recv((char*)&my_packet,sizeof(mypacket))
0
 
LVL 1

Author Comment

by:navigator010897
ID: 6983431
Serva: With #1 If I don't call accept, will I keep getting FD_ACCEPT messages? Plus, what could I do on the client side at that point?  Since the client side is a custom program also, it'd be nice to display an error message of some sort (ie: server is full vs server not responding, if I just don't do the accept, that could be indicative of a server not responding instead of a server is full... see where my problem is?)


makerp: So casting to char would be my easiest solution to avoid having to go thru the whole htons ntohs thing?  The only problem I could see is what if I don't know the size of my packet...  Unless I do make a union'd struct, the size of each packet could be variable depending on which packet struct I use.  

The reason I say this is - the MOTD struct would end up being big, 500 to 1000 bytes.  If I union'd and the MOTD was the biggest, I'd be sending 500 to 1000 bytes each time, which is more then I want to send / receive per update.

Plus, wouldn't it always return a failure, since:
if(res == SOCKET_ERROR || so_far == 0)

so_far == 0 in the first pass, even if res is ok, so_far is still 0 - would that need to be an &&?

Would it be possible to do the following:

// Assumes a char buffer would be passed rather then the
// actual packet structure because we don't know it yet...
int recv(char *buffer,int *PacketType)
{
int so_far = 0;
int len;
struct TH_Struct {
   short type;
   short len;
} *TempHdr;

BOOL Done = FALSE;

    res = recv(sock,buffer + so_far,4,0); //assumes length is in first 4 bytes
    if(res == SOCKET_ERROR || so_far == 0)
    {      
        return FAILURE;
    }
// error check that 4 bytes received, ignored for now
// for simplicities sake
  TempHdr = (struct TH_Struct *)buffer;
  len = TempHdr->len
  *PacketType = TempHdr->type;

  //Make sure len <MAXPACKETLEN

 so_far+=res;


while(!so_far < len)
{
    res = recv(sock,buffer + so_far,len - so_far,0);
    if(res == SOCKET_ERROR || so_far == 0)
    {      
        return FAILURE;
    }
    so_far += res;
 }
 return so_far;
}

the call it
char Buffer[MAXPACKETLENGTH]

recv(Buffer,&PacketType)
 
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 1

Expert Comment

by:seva
ID: 6984139
You have the choice whether to handle "Server busy"
on the client or on the server.

If you want to do it on the server, then of course
you need to call accept for every incoming connection and
return "server busy" message, then closing the connection.

On the other hand, you can set timeout on the client
when connecting and if it expires, display the appropriate
message.

makerp is right about the recv() function, I forgot that one needs MSG_WAITALL flag for my version to work, but I think WinSock does not support this flag.

You still need ntoh() hton() conversions if you want to run
your program on different platforms.

Your idea about the message header is exactly right,
though when reading the header you also need to do it inside while { } since there is no guarantee that the call
to recv returns all header bytes.

Yes, there is a mistake with using so_far.
I usually use the other way:

int nleft = len;
while (nleft > 0)
{
  nread = recv(...);
  ...
  nleft -= nread;
}

 

0
 
LVL 1

Expert Comment

by:seva
ID: 6984149
P.S.
You will receive FD_ACCEPT messages if you requested to
receive those messages.
There is nothing to do about it, and I don't think
it is a big problem.
0
 
LVL 1

Author Comment

by:navigator010897
ID: 7012910
Thanks for the help, I did figure out Async sockets enough to make the program work.... it just wasn't fun ;)
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article shows how to make a Windows 7 gadget that accepts files dropped from the Windows Explorer.  It also illustrates how to give your gadget a non-rectangular shape and how to add some nifty visual effects to text displayed in a your gadget.…
This article describes how to add a user-defined command button to the Windows 7 Explorer toolbar.  In the previous article (http://www.experts-exchange.com/A_2172.html), we saw how to put the Delete button back there where it belongs.  "Delete" is …
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…

910 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now