Solved

Async Winsock Questions

Posted on 2002-04-30
6
596 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
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 
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

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Entering time in Microsoft Access can be difficult. An input mask often bothers users more than helping them and won't catch all typing errors. This article shows how to create a textbox for 24-hour time input with full validation politely catching …
Whether you've completed a degree in computer sciences or you're a self-taught programmer, writing your first lines of code in the real world is always a challenge. Here are some of the most common pitfalls for new programmers.
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…
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…

757 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

17 Experts available now in Live!

Get 1:1 Help Now