TCP Winsock: accept multiple connections/clients
Of course new clients cannot be accepted because the server handles just accepted client, i.e. the server is busy.
The solution is simple: create a new thread for each accepted client and handle the client session there. Just use _beginthreadex()
(#include <process.h>
):
unsigned __stdcall ClientSession(void *data)
{
SOCKET client_socket = (SOCKET)data;
// Process the client.
}
int _tmain(int argc, _TCHAR* argv[])
{
...
SOCKET client_socket;
while ((client_socket = accept(server_socket, NULL, NULL))) {
// Create a new thread for the accepted client (also pass the accepted client socket).
unsigned threadID;
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, &ClientSession, (void*)client_socket, 0, &threadID);
}
}
By the way, send()/recv()
functions do not guarantee that all the data would be sent/received at one call. Please see the documentation for return value of these functions.
C++ Winsock Server with Multiple Clients?
You need one socket per TCP connection, i.e. one per remote IP/port pair. You only need to call WSAStartup
once to initialize winsock library.
Handling multiple users using WinSock
The problem I run into is that the
accept()
function always returnSOCKET_ERROR
.
That is because you are passing it an invalid SOCKET
handle (had you bothered to check with WSAGetLastError()
after receiving SOCKET_ERROR
, it likely would have returned WSAENOTSOCK
).
The reason is because your accept()
wrapper function is calling Winsock's accept()
function with a global SOCKET
variable named sock
, but your main()
function never initializes that variable! It is instead initializing a local SOCKET
variable that is also named sock
. You need to either:
get rid of
main()
's localsock
variable somain()
will then use the globalsock
variable.get rid of the global
sock
variable, and havemain()
pass its localsock
variable as an input parameter to youraccept_clients()
function, which can then pass it as an input parameter to youraccept()
function.
How to handle multiple clients on a socket server made with winsock on VB6?
The solution is to have an array of Winsock objects, and create a new one at runtime. The new object you have created accepts the connection request.
So, in your connection request sub, you would have a new socket:
Dim ConnectionCount as long
Private Sub Winsock1_ConnectionRequest(ByVal requestID As Long)
ConnectionCount=ConnectionCount+1
Load Winsocks(ConnectionCount)
Winsocks(ConnectionCount).Accept(requestID)
txtLog = "Cliente conectado. IP : " & _
Winsocks(ConnectionCount).RemoteHostIP & vbCrLf
End Sub
Edit: Here is a tutorial that may help you better than my code: http://www.devx.com/tips/Tip/5488
It follows the same idea.
VB6 Winsock multiple TCP connections problems with DoEvents
Well, I managed to figure out the problem, and have solved it.
The short answer
Do NOT use DoEvents
.. Some data won't be delivered? Well, close the connection ONLY in the SendComplete
event.
The long answer
First thing first:
Why I used DoEvents
in the first place? because some of the sent messages were not being delivered. A lot of articles/questions on the internet suggest using DoEvents
after Socket.SendData
in order to guarantee the data arrival to the receiver.
I digged deeper into this trying to figure out why the messages aren't delivered. I found out that this problem only occurs when closing the connection after sending the message:
Socket.SendData "Message"
'
'
Socket.Close
So, I simply moved the line that closes the connection to the SendComplete
event, removed the DoEvents
sentence -since I don't need it anymore-, and the problem is gone :)
Private Sub sckAccept_SendComplete(Index As Integer)
sckAccept_Close (Index)
End Sub
I hope this could help someone who has the same problem.
TCP: can two different sockets share a port?
A server socket listens on a single port. All established client connections on that server are associated with that same listening port on the server side of the connection. An established connection is uniquely identified by the combination of client-side and server-side IP/Port pairs. Multiple connections on the same server can share the same server-side IP/Port pair as long as they are associated with different client-side IP/Port pairs, and the server would be able to handle as many clients as available system resources allow it to.
On the client-side, it is common practice for new outbound connections to use a random client-side port, in which case it is possible to run out of available ports if you make a lot of connections in a short amount of time.
Related Topics
Is It Okay to Use "And", "Or" etc. Instead of "&&", "||"
Makefile Enforce Library Dependency Ordering
Documenting Preprocessor Defines in Doxygen
What's the Purpose of a Leading "::" in a C++ Method Call
Can Virtual Functions Be Constexpr
Rotating a 2D Pixel Array by 90 Degrees
Qt - Qpushbutton Text Formatting
Std::Set Iterator Automatically Const
Is It a Strict Aliasing Violation to Alias a Struct as Its First Member
How to Know When a New Usb Storage Device Is Connected in Qt
What Is a Possible Workaround for Object Slicing in C++
Why Was the Restriction on the Comma Operator Being in a Constant Expression Removed in C++11
How Would You Benchmark the Performance of a Function
Value-Initializing an Automatic Object