Solved

Sockets, multiple connections

Posted on 2001-06-17
15
199 Views
Last Modified: 2013-11-20
I currently have a server program which accepts connections from clients but i'm having problems with establishing multiple connections. My prob. is that whatever the last client was to connect is the only one i can talk to. The server prog. just accepts like which i know is the prob. but how do i fix it?

  m_sListenSocket.Accept(m_sConnectSocket);
0
Comment
Question by:scooter1
  • 5
  • 4
  • 2
  • +4
15 Comments
 
LVL 49

Expert Comment

by:DanRollins
ID: 6201243
How do you know that it accepts only one connection?  Show the programming code that you used to learn this fact.

-- Dan
0
 
LVL 10

Expert Comment

by:makerp
ID: 6201488
you need to start a new thread for each client, if you just call a function to deal with a client and call it as a normal function then this will take the main thread of control and you ont accpet a new connection on your server socket until the client function returns.

heres the jist, its a console app so you will need to use AfxBeginThread for thread creation with MFC (look this up in help)

/*
     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>

/* 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__);

     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 32

Expert Comment

by:jhance
ID: 6201802
>>you need to start a new thread for each client

Not true!!  This might be useful but it is ABSOLUTELY NOT A "NEED"!!  In fact, making a WINSOCK application multi-threaded usually just complicates matters rather than clearing them up.

I think you are just not using accept() correctly and are continuing to use the original listening socket for communications rather than the copy that accept() gives you.

Please post your code and I'm sure the solution will be obvious...
0
 
LVL 10

Expert Comment

by:makerp
ID: 6201891
okay, i agree, you can use select to poll sockets, this way you can serve multiple clients at once. you have to ensure you dont spend to long with each client otherwise the others will not get any service. in my expirence this is harder to get right than threads.

one problem with threads is that if threads are created to do small jobs for clients and then end, the effort creating the thread can be more than the threads work itself, in this case you need to employ thread resuse, fun fun fun
0
 
LVL 32

Expert Comment

by:jhance
ID: 6201910
>>you can use select to poll sockets,


NO, NO, NO!!!  This is even worse than using threads.

WINSOCK provides the asynchronous set of sockets functions, all prefixed with WSA.  If you use these, Windows will send your application messages when things happen in your sockets.  You can handle all your socket connections in a single threaded app.  About the only time you might consider using a thread is in response to a WINSOCK message where you need some time to process but don't want to keep any other sockets from being delayed too long.  So it may make sense to start a thread to complete the socket transaction.
0
 
LVL 10

Expert Comment

by:makerp
ID: 6201935
cool, i never really have used the asynchronous socket stuff. all of the stuff i have done that deals with multiple clients i have develped as console apps with no message passing etc. i will look into this , you learn something everyday, cheers jhance.
0
 
LVL 32

Expert Comment

by:jhance
ID: 6201999
About the only time I might suggest using the blocking sockets functions on Windows would be in a situation where there was a VERY strong need to make the source code common between multiple operating systems.  If it's a Windows only app, then the WSA... WINSOCK calls fit into the Windows messaging architecture perfectly.  Windows is designed to and optimized for handling messages.  

Threads do have a place but they are not a "do-all" solution.  I once was called into the fix a problem where another consultant had built a multi-threaded app that was a type of server.  He had made a thread for every socket and when 20 incoming connections happened, the app quickly generated 20 threads.  Well, every thead takes resources and the app was performing miserably.  I rearchitected it from the beginning with no threads at all (in spite of objections from some of the technical staff at the company who thought that threads = performance).  Using only the async WINSOCK calls and handling messages the app was able to handle virtually any number of incoming request with no degradation in performance.  I'm sure there is a limit but in this case the limit was not explored.  In our tests, 20 connections were handled as fast as 2 connections and the customer was happy.  Using threads the performance at 20 connections was about 25% of the performance at 2.

Which leads me to restate a maxim I heard long ago:

"Just because something CAN be done, doesn't mean it SHOULD be done."
0
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 
LVL 32

Expert Comment

by:jhance
ID: 6202006
One other thing.  In Windows, you NEVER POLL for anything.  If you think you must poll something, keep looking for another way.  
0
 
LVL 10

Expert Comment

by:makerp
ID: 6202045
true, i think people like to write multi-threaded apps just because of teh word 'thread', ohh multithreaded = complicated/good coder/performance etc etc. well obviously that aint true at all. i am still new (1 year at uni) to the C++/MFC game and there is still alot to learn. i must investigate the message passing architecture, at present i only use within GUI apps not server based software
0
 
LVL 2

Expert Comment

by:agriggs
ID: 6202612
I have had very good luck with using the CAsyncSocket message-based MFC classes.  There are some examples of their use in the MSDN, one being a simple HTTP server.

I completely agree that in this case, threads are the wrong way to go.
0
 
LVL 1

Expert Comment

by:nivel
ID: 6203568
I recommend using threads and CSockets. It is simple to use and most application don't need that last microsecond of performance that you may (or may not) gain.

I usually use code that looks similar to this:

lSocket.Listen();
do {
  rc = lSocket.Accept(aSocket);
  if (rc) {
    new CAccepter(aSocket.Detach());
    aSocket.Close();
  }
} while (!done);

CAccepter::CAccepter(HSOCKET h) {
  m_hSocket = h;
  AfxBeginThread(ThreadEntry, this);
}

static UINT CAccepter::ThreadEntry(LPVOID arg)
{
  AfxSocketInit();
  ((CAccepter*)arg)->Accept();
  delete ((CAccepter*)arg);
  return 0;
}

void CAccepter::Accept()
{
  CSocket socket;
  socket.Attach(m_hSocket);
  ...
  socket.Close();
}
0
 

Author Comment

by:scooter1
ID: 6203794
there isn't really much to show

void CNetworkDlg::OnBconnect()
{
     m_sListenSocket.Create(m_iPort);
     m_sListenSocket.Listen();
     
     GetDlgItem(IDC_BCONNECT)->EnableWindow(FALSE);       GetDlgItem(IDC_ESERVNAME)->EnableWindow(FALSE);
     GetDlgItem(IDC_RSERVER)->EnableWindow(FALSE);
     GetDlgItem(IDC_ESERVPORT)->EnableWindow(FALSE);

     GetDlgItem(ID_BCLOSE)->EnableWindow(TRUE);    
}

void CNetworkDlg::OnAccept()
{
    m_sListenSocket.Accept(m_sConnectSocket);    

   GetDlgItem(IDC_EMSG)->EnableWindow(TRUE);
   GetDlgItem(IDC_BSEND)->EnableWindow(TRUE);
         
}


when clients connect each one is able to talk to the server but the server only talks to the last one to connect because it becomes 'm_sConnectSocket' i guess. I need to keep track of each client somehow, how?
0
 
LVL 1

Expert Comment

by:nivel
ID: 6208241
When you execute the Accept it overwrites your socket, so you can no longer communicate on that socket (as you said). What you need is perhaps an array of CSockets, but then you are back at the problems discussed above, how to listen to all of them at the same time.

The by far easiest way is to start up a new thread for each connection. Then every thread needs only care about its own connection. I usually also create a new object for each connection.

So each connection has its own object and its own thread, as I showed above.
0
 
LVL 32

Accepted Solution

by:
jhance earned 100 total points
ID: 6208655
>>The by far easiest way is to start up a new thread for each connection

By far the easiest way is to just create a new CSocket * for each new connection.  Then you can delete then when the connections close or time them out eventually if they have died.  Using a thread for every connection is a sure fire way of bringing a Windows system to its knees!!
0
 
LVL 9

Expert Comment

by:ShaunWilde
ID: 6209853
> Using a thread for every connection is a sure fire way of bringing a Windows system to its knees!!

I agree - if you are only having a limited number of connections then this is okay but if you are handling 100s of connections this is not sensible - the best bet would be to pool your connections eg have a maximum of 10 threads and then spread you connections amongst them - you could even spread the busiest connections amongst the pool so that they are not in the same thread but this will only provide minor improvement - the other thing is to not to keep closing and opening threads but to grow to a max number and then stop growing and start spreading your connections.

1 strategy I have seen work is a protocol that told the server that the client wanted to send a large chunk of data and the server would create(use from pool) a thread to handle this connection for the duration of the large chunk (several MB) while all the other threads dealt with the low volume traffic.
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Host to IP 7 73
matchUp  challenge 9 72
sumHeights2  challenge 7 78
how to split multiple lines delimiter : 8 54
Introduction: Dynamic window placements and drawing on a form, simple usage of windows registry as a storage place for information. Continuing from the first article about sudoku.  There we have designed the application and put a lot of user int…
If you use Adobe Reader X it is possible you can't open OLE PDF documents in the standard. The reason is the 'save box mode' in adobe reader X. Many people think the protected Mode of adobe reader x is only to stop the write access. But this fe…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…

759 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

22 Experts available now in Live!

Get 1:1 Help Now