Socket connect abort from a detached thread - c++

I´m building a socket client where I need to implement timeout for connections, read, writes and also timeout for the protocol itself (lack of answer, etc.).
I´m thinking of using a simple timer in a detached thread that will be started on every transaction and then cancelled on transaction completion. This same approach will be used for protocol control using a different timeout.
To test is I did the following simple code:
#include <string>
#include <sstream>
#include <map>
#include <iostream>
#include <cstring>
#include <thread>
#ifdef _WIN32
#include <io.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <Windows.h>
#else
#include <unistd.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
bool timerOn = false;
int currentSocket = 0;
void Timer(int seconds)
{
int tick = seconds;
while (tick > 0)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
tick--;
}
if (timerOn)
close(currentSocket);
}
void StartTimer(int seconds)
{
timerOn = true;
std::thread t(&Timer, seconds);
t.detach();
}
void StopTimer()
{
timerOn = false;
}
void Connect(std::string address, int port)
{
struct addrinfo hints;
struct addrinfo *result = NULL;
struct addrinfo *rp = NULL;
int sfd, s;
std::memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Allow IPV4 or IPV6 */
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = 0;
hints.ai_protocol = 0;
std::string portStr;
portStr = std::to_string(port);
s = getaddrinfo(address.c_str(), portStr.c_str(), &hints, &result);
if (s != 0)
{
std::stringstream ss;
ss << "Cannot resolve hostname " << address << gai_strerror(s);
throw std::runtime_error(ss.str());
}
for (rp = result; rp != NULL; rp = rp->ai_next)
{
sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (sfd == -1)
continue;
StartTimer(10);
int sts = connect(sfd, rp->ai_addr, rp->ai_addrlen);
StopTimer();
if (sts == 0)
break;
close(sfd);
}
freeaddrinfo(result); /* Object no longer needed */
if (rp == NULL)
{
std::stringstream ss;
ss << "Cannot find server address at " << address << " port " << port;
throw std::runtime_error(ss.str());
}
currentSocket = sfd;
}
int main()
{
try
{
Connect("192.168.0.187", 9090);
std::cout << "Connected to server. Congrats!!!" << std::endl;
}
catch (std::exception& ex)
{
std::cout << "Error connecting to server. Aborting." << std::endl;
std::cout << ex.what() << std::endl;
}
}
Closing the socket on timer is not canceling the 'connect' operation, forcing it to abort with error. I´ve tried also shutdown(sfd, SHUT_RDWR); with no success...
Is my approach invalid ? Why is it not working ?
How to force connect to abort with error from the detached thread ?

Closing the socket on timer is not canceling the 'connect' operation, forcing it to abort with error.
Whoa! You absolutely can't do that. There's no possible way to know that the thread is actually blocked in connect (as opposed to being about to call connect) when you close the socket. Releasing a resource in one thread while another thread is, or might be, using it is a recipe for disaster.
Imagine this happens:
A thread is about to call connect, so it arranges for a timeout.
The timeout expires and the socket is closed.
A thread in some library creates a new socket to use for some reason of its own, getting the same socket descriptor.
The thread that was about to call connect finally gets scheduled and calls connect -- connecting the library's socket! Disaster.
You have two choices:
Use a non-blocking connect operation.
Use something like a signal to interrupt the thread that calls connect.
But I have to wonder why you are bothering. Why do you need to abort the connect? If you need to do something else if the connect hasn't succeeded before the timeout, just go ahead and do it.

Related

Using std::thread for send and recive data from TCP socket

I'm developing a TCP socket client. I am trying to write a client that have individual thread for send and receive data. but when I use thread, get a runtime error.
The process goes like this:
main.cpp:
#include <iostream>
#include <thread>
#include <string>
#include <chrono>
#include <WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
#include "TCPConnection.h"
SOCKET sock;
void SendRecive(SOCKET *isock) {
// Do-While loop to send and recive data
char buf[4096];
while (true) {
// Prompt the user for some text
cout << "> ";
// Wait for response
ZeroMemory(buf, 4096);
auto byteRecived = recv(*isock, buf, 4096, 0);
if (byteRecived <= 0) continue;
// Echo response to console
cout << "SERVER> " << string(buf, 0, byteRecived) << endl;
}
}
using namespace std;
int main() {
TCPConnection tcpconn("192.168.1.4", 7705, &sock);
SendRecive(&sock);
return 0;
}
TCPConnection.h:
//
// Created by Hamed on 8/21/2021.
//
#ifndef TCPCLIENT_TCPCONNECTION_H
#define TCPCLIENT_TCPCONNECTION_H
#include <iostream>
#include <thread>
#include <string>
#include <WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
class TCPConnection {
public:
SOCKET *isock;
TCPConnection(string ServerIPAddress, int ServerPort, SOCKET *sock);
~TCPConnection();
};
#endif //TCPCLIENT_TCPCONNECTION_H
TCPConnection.cpp:
#include "TCPConnection.h"
TCPConnection::TCPConnection(string ServerIPAddress, int ServerPort, SOCKET *sock) {
// Initialize WinSock
WSAData data{};
WORD ver = MAKEWORD(2, 2);
int wsResult = WSAStartup(ver, &data);
if (wsResult != 0) {
cerr << "Can't start winsock, Err #" << wsResult << endl;
return;
}
// Create socket
*sock = socket(AF_INET, SOCK_STREAM, 0);
if (*sock == INVALID_SOCKET) {
cerr << "Can't create socket, Err #" << WSAGetLastError() << endl;
WSACleanup();
return;
}
// Fill in a hint structure
sockaddr_in hint{};
hint.sin_family = AF_INET;
hint.sin_port = htons(ServerPort);
inet_pton(AF_INET, ServerIPAddress.c_str(), &hint.sin_addr);
// connect to server
int connResult = connect(*sock, (sockaddr *) &hint, sizeof(hint));
if (connResult == SOCKET_ERROR) {
cerr << "Can't connect to server, Err #" << WSAGetLastError() << endl;
closesocket(*sock);
WSACleanup();
return;
}
isock = sock;
}
TCPConnection::~TCPConnection() {
// Gracefully close down everything
closesocket(*isock);
WSACleanup();
}
this code working properly but when I change "main.cpp" to use thread like this:
int main() {
TCPConnection tcpconn("192.168.1.4", 7705, &sock);
thread DoRunTCPRecive(SendRecive,&sock);
return 0;
}
I get "Microsoft Visual C++ Runtime Library" debug error when runing app.
Update:
Actually I want to have a function for send and have another function for receive data . but when I use join, my code stay on current function and I can't run another code after that.
you should join the thread after create it
thread DoRunTCPRecive(SendRecive,&sock);
DoRunTCPRecive.join()

libev + non-blocking socket continuously invokes callback

I'm using libev + non-blocking sockets to send a request to a server. I'm using Keep Alive because I need to send future requests to the destination over this same connection.
Behavior
Run the program and it fetches the URL and logs to console, as expected.
After doing this, wait and don't push ctrl+c to exit the program.
Expected
App should stay open because event loop is waiting for future responses but should not console log anything after the initial response.
Actual
Leave the app running. After 30+ seconds, it will start to console log the same response over and over and over again without end.
Question
Why is libev calling my callback (example_cb) repeatedly when no new request was sent and no new response data was received? How can I fix this?
#include <ev.h>
#include <stdio.h>
#include <iostream>
#include <ctype.h>
#include <cstring>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>
#include <sstream>
#include <fstream>
#include <string>
using namespace std;
void sendRequest(int sockfd)
{
puts("------");
puts("sendRequest() was called");
stringstream ss;
ss << "GET /posts/11 HTTP/1.1\r\n"
<< "Host: jsonplaceholder.typicode.com\r\n"
<< "Accept: application/json\r\n"
<< "\r\n";
string request = ss.str();
if (send(sockfd, request.c_str(), request.length(), 0) != (int)request.length()) {
cout << "Error sending request." << endl;
exit(1);
}
cout << "Request sent. No err occured." << endl;
}
static void delay_cb(EV_P_ ev_timer *w, int revents)
{
puts("------");
puts("delay_cb() was called");
sendRequest(3);
}
static void example_cb(EV_P_ ev_io *w, int revents)
{
puts("------");
puts("example_cb() was called");
int sockfd = 3;
size_t len = 80*1024, nparsed; // response must be <= 80 Kb
char buf[len];
ssize_t recved;
recved = recv(sockfd, &buf, len, 0);
if (recved < 0) {
perror("recved was <1");
}
// don't process keep alives
if (buf[0] != '\0') {
std::cout << buf << std::endl;
}
// clear buf
buf[0] = '\0';
std::cout << "buf after clear attempt: " << buf << std::endl;
}
int example_request()
{
std::string hostname = "jsonplaceholder.typicode.com";
int PORT = 80;
struct sockaddr_in client;
struct hostent * host = gethostbyname(hostname.c_str());
if (host == NULL || host->h_addr == NULL) {
cout << "Error retrieving DNS information." << endl;
exit(1);
}
bzero(&client, sizeof(client));
client.sin_family = AF_INET;
client.sin_port = htons( PORT );
memcpy(&client.sin_addr, host->h_addr, host->h_length);
// create a socket
int sockfd = socket(PF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
cout << "Error creating socket." << endl;
exit(1);
}
cout << "Socket created" << endl;
// enable keep alive
int val = 1;
setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof val);
if (connect(sockfd, (struct sockaddr *)&client, sizeof(client)) < 0) {
close(sockfd);
cout << "Could not connect" << endl;
exit(1);
}
cout << "Socket connected" << endl;
// make non-blocking
int status = fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL, 0) | O_NONBLOCK);
if (status == -1) {
perror("ERROR making socket non-blocking");
}
std::cout << "Socket set to non-blocking" << std::endl;
std::cout << "Sockfd is: " << sockfd << std::endl;
return sockfd;
}
int main(void)
{
// establish socket connection
int sockfd = example_request();
struct ev_loop *loop = EV_DEFAULT;
ev_io example_watcher;
ev_io_init(&example_watcher, example_cb, sockfd, EV_READ);
ev_io_start(loop, &example_watcher);
// used to send the request 2 sec later
ev_timer delay_watcher;
ev_timer_init(&delay_watcher, delay_cb, 2, 0.0);
ev_timer_start(loop, &delay_watcher);
ev_run(loop, 0);
return 0;
}
Edit: Code updated with suggestions from comments
The source of the problem is that you do not check recved == 0 condition which corresponds to the other side closing the connection. When that happens the OS sets the socket into "closed mode" which (at least under linux) is always ready for reading and subsequent calls to recv will always return 0.
So what you need to do is to check for that condition, call close(fd); on the file descriptor (possibly with shutdown before) and ev_io_stop on the associated watcher. If you wish to continue at that point then you have to open a new socket and eo_io_start new watcher.

Proper way to handle SIGTERM with multiple threads

I have a multi threaded program on Raspberry in which I want to handle SIGTERM and shut everything down gracefully. The issue is that I have a background thread that has called recvfrom() on a blocking socket. As per my understanding from the man pages, if I exit my handler all the system calls should be woken up and return with -1 and errno set to EINTR. However in my case the recvfrom call keeps hanging.
1) In general am I understanding this right, that all threads that have blocking system calls that are able to be woken up by a signal should wake up in this scenario?
2) Could it be that the operating system is setting some special signal mask on my thead?
The interresting part is that I am using the VideoCore primitives, not pthread, maybe that could be the cause? Here is a small test example:
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <signal.h>
#include "interface/vcos/vcos.h"
void SignalHandler(int nSignalNumber)
{
std::cout << "received signal " << nSignalNumber << std::endl;
}
void* ThreadMain(void* pArgument)
{
int nSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (nSocket >= 0)
{
sockaddr_in LocalAddress;
memset(&LocalAddress, 0, sizeof(LocalAddress));
LocalAddress.sin_family = AF_INET;
LocalAddress.sin_addr.s_addr = INADDR_ANY;
LocalAddress.sin_port = htons(1234);
if (bind(nSocket, reinterpret_cast<sockaddr *>(&LocalAddress), sizeof(LocalAddress)) == 0)
{
sockaddr_in SenderAddress;
socklen_t nSenderAddressSize = sizeof(SenderAddress);
unsigned char pBuffer[512];
std::cout << "calling recvfrom()" << std::endl;
int nBytesReceived = recvfrom(nSocket, pBuffer, sizeof(pBuffer), 0, reinterpret_cast<struct sockaddr *>(&SenderAddress), &nSenderAddressSize);
if (nBytesReceived == -1)
{
if (errno == EINTR)
{
std::cout << "recvfrom() was interrupred by a signal" << std::endl;
}
else
{
std::cout << "recvfrom() failed with " << errno << std::endl;
}
}
}
else
{
std::cout << "bind() failed with " << errno << std::endl;
}
close(nSocket);
}
else
{
std::cout << "socket() failed with " << errno << std::endl;
}
return NULL;
}
int main(int argc, char** argv)
{
struct sigaction SignalAction;
memset(&SignalAction, 0, sizeof(SignalAction));
SignalAction.sa_handler = SignalHandler;
sigaction(SIGTERM, &SignalAction, NULL);
VCOS_THREAD_T Thread;
VCOS_STATUS_T nVcosStatus = vcos_thread_create(&Thread, "", NULL, ThreadMain, NULL);
if (nVcosStatus == VCOS_SUCCESS)
{
void* pData = NULL;
vcos_thread_join(&Thread, &pData);
}
else
{
std::cout << "vcos_thread_create() failed with " << nVcosStatus << std::endl;
}
return EXIT_SUCCESS;
}
It can be compiled like this:
g++ test.cpp -I/opt/vc/include -L/opt/vc/lib -lvcos -o test
When I run it and then call kill on the running instance the output is:
calling recvfrom()
received signal 15
and the process hangs. I'll try if a pthread behaves differently.
UPDATE
Ok I updated the sample to spawn a pthread thread as well and that one is not quitting as well. So I assume the signals are not populated to all threads?
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include "interface/vcos/vcos.h"
void SignalHandler(int nSignalNumber)
{
std::cout << "received signal " << nSignalNumber << std::endl;
}
void* ThreadMain(void* pArgument)
{
const char* pThreadType = reinterpret_cast<const char*>(pArgument);
int nSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (nSocket >= 0)
{
sockaddr_in LocalAddress;
memset(&LocalAddress, 0, sizeof(LocalAddress));
LocalAddress.sin_family = AF_INET;
LocalAddress.sin_addr.s_addr = INADDR_ANY;
LocalAddress.sin_port = htons(pThreadType[0] * 100);
if (bind(nSocket, reinterpret_cast<sockaddr *>(&LocalAddress), sizeof(LocalAddress)) == 0)
{
sockaddr_in SenderAddress;
socklen_t nSenderAddressSize = sizeof(SenderAddress);
unsigned char pBuffer[512];
std::cout << "calling recvfrom()" << std::endl;
int nBytesReceived = recvfrom(nSocket, pBuffer, sizeof(pBuffer), 0, reinterpret_cast<struct sockaddr *>(&SenderAddress), &nSenderAddressSize);
if (nBytesReceived == -1)
{
if (errno == EINTR)
{
std::cout << "recvfrom() was interrupred by a signal" << std::endl;
}
else
{
std::cout << "recvfrom() failed with " << errno << std::endl;
}
}
}
else
{
std::cout << "bind() failed with " << errno << std::endl;
}
close(nSocket);
}
else
{
std::cout << "socket() failed with " << errno << std::endl;
}
std::cout << pThreadType << " thread is exiting" << std::endl;
return NULL;
}
int main(int argc, char** argv)
{
struct sigaction SignalAction;
memset(&SignalAction, 0, sizeof(SignalAction));
SignalAction.sa_handler = SignalHandler;
sigaction(SIGTERM, &SignalAction, NULL);
VCOS_THREAD_T VcosThread;
VCOS_STATUS_T nVcosStatus = vcos_thread_create(&VcosThread, "", NULL, ThreadMain, const_cast<char*>("vcos"));
bool bJoinVcosThread = false;
if (nVcosStatus == VCOS_SUCCESS)
{
bJoinVcosThread = true;
}
else
{
std::cout << "vcos_thread_create() failed with " << nVcosStatus << std::endl;
}
pthread_t PthreadThread;
int nPthreadStatus = pthread_create(&PthreadThread, NULL, ThreadMain, const_cast<char*>("pthread"));
bool bJoinPthreadThread = false;
if (nPthreadStatus == 0)
{
bJoinPthreadThread = true;
}
else
{
std::cout << "pthread_create() failed with " << nPthreadStatus << std::endl;
}
if (bJoinVcosThread)
{
void* pData = NULL;
vcos_thread_join(&VcosThread, &pData);
}
if (bJoinPthreadThread)
{
void* pData = NULL;
pthread_join(PthreadThread, &pData);
}
return EXIT_SUCCESS;
}
A signal such as SIGTERM is submitted to one thread in the process only. The only precondition is that the chosen thread must either have not masked the signal, or must wait for it using sigwait. The other threads will not be directly notified that the signal has been delivered.
A common approach to combine signals with threads is to have a separate thread which handles signals only and notifies the other threads using thread synchronization mechanisms such as condition variables.
For interrupting file I/O, this may not be sufficient because there is a race condition between checking for a termination request and making the system call to perform the I/O operation. Some language run-time libraries use non-blocking I/O with poll or epoll with a special file descriptor which becomes ready on signal delivery (either using the previously-mentioned thread-based approach, or something Linux-specific like signalfd). Others try to avoid this overhead by using the read and write system calls directly with a complicated dance which uses dup2 to replace the file descriptor with one that always causes I/O to fail, thereby avoiding the race condition (but the bookkeeping needed for that is fairly complicated).
The manpage for signal reads:
If a signal handler is invoked while a system call or library function call is blocked, then either:
the call is automatically restarted after the signal handler returns; or
the call fails with the error EINTR.
Which of these two behaviors occurs depends on the interface and whether or not the signal handler was established using the SA_RESTART flag (see sigaction(2)). The details vary across UNIX systems<...>
A few lines below, recvfrom is listed among the functions that use SA_RESTART behavior by default. (Note: this behavior is disabled if there's a timeout on the socket, though.)
Thus, you should fill the sa_flags field of the sigaction structure to carefully avoid setting the SA_RESTART flag.
A good way to deal with blocking sockets -see socket(7)- (and even non blocking ones) is to use a multiplexing syscall like poll(2) (or the obsolete select(2)....)
Regarding signals, be sure to read signal(7) and signal-safety(7).
A common way to handle signals with some event loop (using poll(2)) is to have a signal handler which simply write(2)-s a byte on a pipe(7) to self (you'll setup the pipe at initialization, and you'll poll it in your event loop). The Qt documentation explains how and why. You might also use the Linux specific signalfd(2).

Improve a server with select() function

I read about select() and also read many examples of it, but I can't understand when can I use it?
I understood that I can use it in the accept() function, in case I want few people to connect to the server, but it has confused me.
I need to built a server that receive data only from 2 clients, 1 every time. The first user sends to the server a string, the string responds and then the second user sends a string.
Can someone help me with combining the select() function in the recv() function?
I've added my server.cpp code. Thank you!
server:
#include <iostream>
#include <winsock2.h>
#include <string>
#include <windows.h>
#include <vector>
#pragma comment(lib,"ws2_32.lib")
#define MAX_NUMBER_OF_PLAYERS 1
#define BUFFER_SIZE 1024
#define LIMIT 1
// server side
#define INVALID_MOVE 00
#define PLEASE_ENTER_A_MOVE 15
#define PRINT_BOARD 20
#define END_GAME 30
// client side
#define MOVE 10
using namespace std;
int main()
{
WSADATA WsaDat;
SOCKET clientsock[2];
int minsock = 0;
int numsocks = MAX_NUMBER_OF_PLAYERS;
if (WSAStartup(MAKEWORD(2, 2), &WsaDat) != 0)
{
std::cout << "WSA Initialization failed!\r\n";
WSACleanup();
system("PAUSE");
return 0;
}
SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (serverSocket == INVALID_SOCKET)
{
std::cout << "Socket creation failed.\r\n";
WSACleanup();
system("PAUSE");
return 0;
}
SOCKADDR_IN serverInf;
serverInf.sin_family = AF_INET;
serverInf.sin_addr.s_addr = INADDR_ANY;
serverInf.sin_port = htons(8888);
if (bind(serverSocket, (SOCKADDR*)(&serverInf), sizeof(serverInf)) == SOCKET_ERROR)
{
std::cout << "Unable to bind socket!\r\n";
WSACleanup();
system("PAUSE");
return 0;
}
listen(serverSocket, 5);
clientsock[0] = accept(serverSocket, NULL, NULL);
cout << "Client 1 has connected." << endl;
clientsock[1] = accept(serverSocket, NULL, NULL);
cout << "Client 2 has connected." << endl;
for (int i = 0; i < 2; i++)
{
cout << "Client " << i+1 << " Has Connected!" << endl;
}
char client1_buffer[BUFFER_SIZE];
char client2_buffer[BUFFER_SIZE];
char* clientBuffer;
// until there isn't a mate.
bool gameRunning = true;
// user represents if it's user1 (0), or user2(1)
bool user = 0;
while (gameRunning)
{
if (!user)
clientBuffer = client1_buffer;
else
clientBuffer = client2_buffer;
int in = recv(clientsock[user], clientBuffer, BUFFER_SIZE, 0);
cout << in << endl;
if (in > 0)
{
// CHECKS
// MOVE COMMAND
// IF worked, send the board to both clients. if current user = 1 ==> do user to 0 | if the user = 0 => do user to 11
// ELSE, send the current client (clientsock[user]) Error message and ask for a command again.
cout << clientBuffer << endl;
cout << " IN RECV";
char* szMessage = "15";
send(clientsock[user], szMessage, sizeof(szMessage), 0);
}
else if (in == 0)
{
// The connection has closed.
// REMEMBER : SAVE THE GAME SITUATION.
}
else
{
printf("recv failed: %d\n", WSAGetLastError());
// SEND ERROR MESSAGE TO BOTH CLIENTS
}
user = !user;
}
// Shutdown our socket
shutdown(serverSocket, SD_SEND);
// Close our socket entirely
closesocket(serverSocket);
WSACleanup();
system("pause");
return 0;
}
Ok, now that you corrected your code, I have to do some work.
I suggest you remove this
user = !user
and add this immediately after the beginning of the while loop:
{
int nfds = 0; // smallest number higher than all socket descriptors
fd_set set; // this contains garbage from the stack, thus ...
FD_ZERO(&set); // first clean it and then add both client sockets:
FD_SET(clientsock[0],&set); if(nfds<=clientsock[0]) nfds=clientsock[0]+1;
FD_SET(clientsock[1],&set); if(nfds<=clientsock[1]) nfds=clientsock[1]+1;
select(nfds,&set,0,0,0); // this uses and changes the content of set
bool next = !user; // next is the other user, and we try to serve it:
if(FD_ISSET(clientsock[next],&set)) user=next;
}
By the way, I like your creative way of using bool as an index, though once you have more than 2 clients, you might have to change that concept.
My code implements a little bit of scheduling policy: If there is data available from both clients, it reads from that client from which it did not read data the previous time. If, instead, you want to read lots of data from one client and then lots of data from the other, replace the lines containing next by
if(!FD_ISSET(clientsock[user],&set)) user=!user;
The first version tries to alternate as often as possible, while the second tries to read as much data as possible from the same client before switching to the other.

VC11 Winsock Application Won't Shut Down

I have an interesting scenario for a winsock app that seemingly will not close. The following is enough code to fully replicate the issue:
#include "stdafx.h"
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")
#include <WS2tcpip.h>
#include <MSTcpIP.h>
#include <ws2ipdef.h>
#include <cstdio>
#include <iostream>
using namespace std;
int main() {
WSAData wsaStartup;
WSAStartup(MAKEWORD(2, 2), &wsaStartup);
SOCKET s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
addrinfo *result;
addrinfo hint = { 0 };
hint.ai_family = AF_INET6;
int error = getaddrinfo("localhost", "45000", &hint, &result);
if (error || !result) {
cout << "Unable to resolve host. " << WSAGetLastError() << endl;
return 1;
}
error = connect(s, result->ai_addr, result->ai_addrlen);
if (error == SOCKET_ERROR) {
cout << "Unable to connect to host. " << WSAGetLastError() << endl;
} else {
cout << "Connection successful." << endl;
}
freeaddrinfo(result);
closesocket(s);
WSACleanup();
return 0;
}
I have spent numerous hours trying to track the issue down. It seems like getaddrinfo and connect both spawn an nt thread that hangs out, and prevents the app from terminating.
The only important compiler option that I changed here is: Linker->Advanced->EntryPoint where I specified "main". If I get rid of that compiler option, and change the main signature to:
int _tmain(int argc, _TCHAR* argv[])
everything seems to work fine. In my use case, I am fine having the above _tmain function, but I am wondering if anyone has any idea what magic is going on behind the scenes of the _tmain function that is making the app close.
How do I correctly set the entry point for an exe in Visual Studio?
Perhaps you need to provide the correct signature for main() to match what the runtime is expecting.