Solved

Winsock Programming Question

Posted on 2002-04-11
10
327 Views
Last Modified: 2013-12-03
I'm having a little trouble figuring out how to handle something.

Ok, here's the situation:

1) The server must be able to handle multiple connections
   possible solutions I have thought of are:
      threaded, each new connection gets thrown into a
      new thread (yuck)
   Solution I would like, but have no clue how to implement:
      Standard loop with rest of the program, as the server already performs other tasks, and could output as needed.  During the loop, it would check for new connections, and send and receive data from existing connections.

2) The server can't wait for a connection, it needs to do its processing regardless, but must be able to accept a connection.

Although this is not a game that I am toying with, one could think of it as a simple game server, the game logic needs to process, updating clients, while waiting for new clients.

Kicker:  I want to use both udp and tcp.  udp for some clients, tcp for others - ie: player can be udp, packets are ok to loose, admin needs tcp to guarantee messages/responses.

I'm trying to find good, easy to follow information to help me complete my little program.  I am writing both the client and the server.

This is NOT a school project, but rather my own attempt to learn and understand winsock to use in more important apps later.  I am mostly looking just for a reference, good sites or books that could help me learn and understand.

(ps - sending me to udp sites for the daytime protocol won't cut it, been reading those left and right at about every site that talks about winsock programming their servers wait for clients and can only handle one client at a time)

Any help would be appreicated, I just can't seem to find quality info beyond how to write a daytime server and client.

Final note - NOT MFC, NOT JAVA.  I would prefer C based solutions (as that is what I program in mostly now adays), although I would entertain C++ solutions if I could figure out how to implement them.

I realize that Unix sockets programming is similar, but I would prefer a Winsock based example as this app will require Windows.
0
Comment
Question by:navigator010897
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
10 Comments
 
LVL 1

Expert Comment

by:Pavlik
ID: 6937286
Look at the WSAEventSelect() function.

Initially socket is in blocking mode. This means that accept() function returns only when connection accepted.
WSAEventSelect() turns socket into non blocking mode. You should specify event object and after that none of the socket function will block execution. For example accept() will return immediately after call. All that you should do is to WaitForSingleObject() and after that WSAEnumNetworkEvents() to determine if connection was accepted.
After you have accepted connection you simply assign it to the same event. But in this case you will need to go through all your accepted socket to determine which one signaled event.

Look at the documentation and if you would be interested in such solution i'll write short example for you.

Best regards,
Pavlik
0
 
LVL 1

Author Comment

by:navigator010897
ID: 6938461
Would I be better off doing a threaded approach?

My biggest problem that I see, if I were to take the threaded approach (which appears to be a simpler, cleaner method) would be having the thread that processes each socket obtain the appropriate info from the master thread.

ie:
1 thread per connection
1 thread handling a message of the day, checking the MOTD file for a change ever 5 minutes or so (really not a MOTD, but you get the idea)
main program handling connections and creating threads.

now my problem is, if person A says something - getting that text from person A and sending it to person B and C.  Also if there is an update on the MOTD, sending that to A, B and C.

So, either I need to do it all in one master program with the WSAEventSelect with no threads, where the MOTD file is parsed based upon a timer, but everything else is handled in a straight loop.  Or I need to implement it with threads.

Max users on this might only be 10.

Which path do you think would be more efficient, and easier to build?  Although I was thinking of moving away from threads due to my lack of use of threads, but I am wondering - would they really be better?

Either way, if you do have some sample code you could point me to, I would really appreciate it.
0
 
LVL 5

Expert Comment

by:robpitt
ID: 6938761
With proper structuring you can do everything efficently in one thread. I advise you read up on the select() and ioctlsocket() functions.

select() can be used to determine which (if any) from a set of sockets are ready for reading/writing.

ioctlsocket() has multiple uses including determining exactly how much data is ready for reading in a subsequent recv() call.




void ProcessSockets()
{
    //Recv all data that winsock has ready on all our sockets

    do
    {
        //Build a list of all our sockets
        fds.fd_count=numSockets;
        for (i=0;i<numSockets;i++)
        {
            fds.fd_array[i]=socketArray[i];
        }
       
        //Timeout of 0
        tv.tv_sec=0;
        tv.tv_usec=0;
       
        //Now find first socket with data in them
        sockIndex=select(0,&fds,NULL,NULL,&tv);
       
        if (sockIndex>=0)
        {
            //Read/process data from socket e.g. do a recv() on it!
            ProcessSocket(sockIndex);
        }
    }while(sockIndex>=0);//Repeat until no sockets have data in them
}
0
PeopleSoft Has Never Been Easier

PeopleSoft Adoption Made Smooth & Simple!

On-The-Job Training Is made Intuitive & Easy With WalkMe's On-Screen Guidance Tool.  Claim Your Free WalkMe Account Now

 
LVL 10

Accepted Solution

by:
makerp earned 200 total points
ID: 6941289
if your connection between client and server is fairly long lived then threads are a viable answer, but if you hundreds of client you may end up with too many threads. anyway here is a server example using multiple threads, remeber to link to a multithreaded run time.

/*
     Written By     :     Paul Maker
     Description :     a simple console app. its a echo server
                         to demonstrate stream sockets.

     NO ERROR CHECKING
*/

/* run-time stuff */
#include <stdio.h>
#include <stdlib.h>
/* _beginthread */
#include <process.h>
/* err, winsock */
#include <winsock2.h>

#include <conio.h>

#define BROWSER_OUTPUTER

/* thread controling function */
void __cdecl do_connection(void *socket)
{
     SOCKET client = (SOCKET)socket;
     char buffer[1000];

     while(true)
     {
          int r = recv(client,buffer,sizeof(buffer),0);    
          if(r == 0 || r == SOCKET_ERROR) break;
          send(client,buffer,sizeof(buffer),0);
     }

     closesocket(client);
}

int main(int argc, char *argv[])
{
     printf("Demo Echo server : Paul Maker %s %s\n",
             __DATE__,__TIME__);
     getch();
     WSADATA wsaData;
     if(WSAStartup(0x202,&wsaData) == SOCKET_ERROR)
     {    
     printf("Error : %d\n",WSAGetLastError());
          return 0;
     }                
     /* create the socket */
     SOCKET sock = socket(AF_INET,SOCK_STREAM,0);
     struct sockaddr_in our_addr;
     /* set up our address */
     our_addr.sin_family = AF_INET;
     our_addr.sin_addr.s_addr = ADDR_ANY;
     our_addr.sin_port = htons(atoi(argv[1]));
     /* bind to it */
     if(bind(sock,(sockaddr*)&our_addr,sizeof(sockaddr_in))
          == SOCKET_ERROR)
     {
          printf("Error : %d\n",WSAGetLastError());
          return 0;
     }
     /* set it to a passive mode */
     if(listen(sock,10) == SOCKET_ERROR)
     {    
          printf("Error : %d\n",WSAGetLastError());
          return 0;
     }

     SOCKET c;
     while(true)
     {
          struct sockaddr_in client;
          int client_len = sizeof(sockaddr_in);
          /* accept the connection */
          c = accept(sock,(sockaddr*)&client,&client_len);
          /* start a new thread to deal with it  */
          _beginthread(do_connection,0,(void*)c);
     }

     closesocket(sock);

     return 1;
}
0
 
LVL 1

Author Comment

by:navigator010897
ID: 6942031
makerp - I had noticed a server very similar in code to yours, my only problem is figuring out communication, which was why I wasn't sure if threading would work - if it could, I would prefer the main server listening be in a seperate thread - and this is why:

I need to have a file parsed on a regular basis (regular time intervals) - right now, the test code I have is using a WM_TIMER message to handle this - of course, this wouldn't work out well if the main thread of the program is hung up waiting for connections.  

So - if I went threaded, does anyone kow if I could put the listening into a thread?  


Pavlik - If you could whip up a wndproc section (and any needed functions) that demonstrates handling the server in a single thread, but multiple connections, I would appreciate it.  It doesn't need to be a complete program - I can easily put all of the other code in place to make it work - I just don't understand the process yet on a single thread, multiple connection server.

Robpitt - I honestly don't know how to implement the example under windows sockets, it appears your sample is for *nix - I've been going thru MSDN hell to figure it all out, but I haven't gotten it together yet.

To all that have posted:  I have been looking up in MSDN, unfortunately, it gives some basic description of things like WSAEventSelect and WSAAsyncSelect, etc. but they really don't seem to have much sample code which would make life easier in terms of understanding.

Thanks again for everyones suggestions!
0
 
LVL 10

Expert Comment

by:makerp
ID: 6942036
put the body of main in a seperate function then _beginthread it as i am doing with the client. but remeber when main end all child threads will end to so make sure your primary thread is always doing something
0
 
LVL 1

Author Comment

by:navigator010897
ID: 6942106
Well, my thought was since this was/is going to be a windows program - it will have a "logging" display (things like who is connected and what-not) as well as a few configuration things (ie: adding users as authentication of some sort will be required, etc.)

Now, in your threaded example, you have the parameter for the threads being their given socket. What can I do regarding the actual data passed.

Lets say it was a program where the data that came in requires processing by the server (help, looking something up, a line of text that needs to be broadcast, etc.) the server main thread (or a seperate thread) would need to process that data, and prepare data to go out (whether it be to return data to the original connection, or to broadcast).

What's the best way of handling this?  A general global variable, or would it be better to have that thread variable (void *socket) be a struct to also contain a queue and such?

I'm sorry for asking so many stupid questions, but so many of the examples out there are so basic, like echoing characters or single thread, single connection basic web clients or servers.  I haven't been able to locate and really stripped down servers that offer non-error checked, REALLY basic functionality (if I could find a chat server and client - especially one that was threaded, I think I would be able to understand these concepts much easier, and not ask as many stupid questions - the only source I have been able to find is one in MFC, which hides so much, I can't figure out how to make it work in the API).  I really appreciate all of the help.  If more points need to be assigned for the complexity of the question, let me know and I'll be happy to add some on.
0
 
LVL 10

Expert Comment

by:makerp
ID: 6942125
what you can do is hold a list of connected sockets. in the client thread you can do what you like with the local client connection, as i am in my exmaple, just sending back what the client sent. if you need to broadcast you can loop through the global list of client sockets and send to each. i dont think you can multi-cast using tcp (or broadcast).

in anycase managing this list will be a task i its self, To be quite honest if i was you build your framework piece at a time. get a skelton working then ask specific quetsions regarding your current code.
0
 
LVL 1

Author Comment

by:navigator010897
ID: 6942295
Yes, you are right.  I'll get some code worked up and then post again here if I run into trouble, otherwise I'll give grade at this point - thank you for all of your suggestions makerp, it really has helped.
0
 
LVL 1

Author Comment

by:navigator010897
ID: 7011954
It provided the basis of my server.  It took a while to get it in and tested (I needed my client app up and running to make sure the server code framework was operational).  

After I had the client running, I thought about your comment about threaded, and swapped the server from a threaded server to a single process server using FD_SET's.
0

Featured Post

[Webinar] Learn How Hackers Steal Your Credentials

Do You Know How Hackers Steal Your Credentials? Join us and Skyport Systems to learn how hackers steal your credentials and why Active Directory must be secure to stop them. Thursday, July 13, 2017 10:00 A.M. PDT

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.…
With most software applications trying to cater to multiple user needs nowadays, the focus is to make them as configurable as possible. For e.g., when creating Silverlight applications which will connect to WCF services, the service end point usuall…
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…
Do you want to know how to make a graph with Microsoft Access? First, create a query with the data for the chart. Then make a blank form and add a chart control. This video also shows how to change what data is displayed on the graph as well as form…

617 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