Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 340
  • Last Modified:

Winsock Programming Question

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
navigator010897
Asked:
navigator010897
1 Solution
 
PavlikCommented:
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
 
navigator010897Author Commented:
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
 
robpittCommented:
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
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

 
makerpCommented:
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
 
navigator010897Author Commented:
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
 
makerpCommented:
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
 
navigator010897Author Commented:
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
 
makerpCommented:
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
 
navigator010897Author Commented:
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
 
navigator010897Author Commented:
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
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now