Solved

Winsock Programming Question

Posted on 2002-04-11
10
314 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
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
 
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
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 
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

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

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 …
What my article will show is if you ever had to do processing to a listbox without being able to just select all the items in it. My software Visual Studio 2008 crystal report v11 My issue was I wanted to add crystal report to a form and show…
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…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

708 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

14 Experts available now in Live!

Get 1:1 Help Now