I'am trying to set my own timeot for connect() function.
my code works well with default connection like this:
bool connectFUNC4(char * ipaddr) {
WSADATA wsa;
struct sockaddr_in server;
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
return false;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
return false;
server.sin_addr.s_addr = inet_addr(ipaddr);
server.sin_family = AF_INET;
server.sin_port = htons(5577);
if (connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0)
return false;
return true;
}
I understand idea with blocking and not blocking connection, and I've found solution with setting to nonblocking mode and timeout. It always finished successful but communication does not work.
bool connectFUNC3(char * ipaddr) {
WSADATA wsa;
struct sockaddr_in server;
server.sin_addr.s_addr = inet_addr(ipaddr);
server.sin_family = AF_INET;
server.sin_port = htons(5577);
unsigned long block = 1;
ioctlsocket((unsigned int)sock, FIONBIO, &block);
WSAGetLastError();
int ret = connect(sock, (struct sockaddr *)&server, sizeof(server));
timeval time_out;
time_out.tv_sec = 5;
time_out.tv_usec = 0;
fd_set setW, setE;
FD_ZERO(&setW);
FD_SET(sock, &setW);
FD_ZERO(&setE);
FD_SET(sock, &setE);
select(0, NULL, &setW, &setE, &time_out);
bool flag;
if (FD_ISSET(sock, &setW))
{
// connection successful
flag = true;
}
else if (FD_ISSET(sock, &setE))
{
// connection fail
flag = false;
}
else
{
// connection timeout
flag = false;
}
block = 0;
ioctlsocket((unsigned int)sock, FIONBIO, &block);
return flag;
}
Please help to make it work, or to find another solution (multithread not usable in my case). Thank you.
Neither of your functions are checking ANY return values for errors. And when calling select() in non-blocking mode, call it only if connect() fails with a WSAEWOULBLOCK error, and if select() then returns > 0 then you should be checking setE first and not setW.
Try something more like this:
void closesock(SOCKET *s)
{
// preserve current error code
int err = WSAGetLastError();
closesocket(*sock);
*sock = INVALID_SOCKET;
WSASetLastError(err);
}
bool connectFUNC4(char * ipaddr)
{
// you really shouldn't be calling WSAStartup() here.
// Call it at app startup instead...
struct sockaddr_in server = {0};
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(ipaddr);
server.sin_port = htons(5577);
// ipaddr valid?
if (server.sin_addr.s_addr == INADDR_NONE)
return false;
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
return false;
if (connect(sock, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
// connection failed
closesock(&sock);
return false;
}
// connection successful
return true;
}
bool connectFUNC3(char * ipaddr)
{
// you really shouldn't be calling WSAStartup() here.
// Call it at app startup instead...
struct sockaddr_in server = {0};
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(ipaddr);
server.sin_port = htons(5577);
// ipaddr valid?
if (server.sin_addr.s_addr == INADDR_NONE)
return false;
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
return false;
// put socked in non-blocking mode...
u_long block = 1;
if (ioctlsocket(sock, FIONBIO, &block) == SOCKET_ERROR)
{
closesock(&sock);
return false;
}
if (connect(sock, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
if (WSAGetLastError() != WSAEWOULDBLOCK)
{
// connection failed
closesock(&sock);
return false;
}
// connection pending
fd_set setW, setE;
FD_ZERO(&setW);
FD_SET(sock, &setW);
FD_ZERO(&setE);
FD_SET(sock, &setE);
timeval time_out = {0};
time_out.tv_sec = 5;
time_out.tv_usec = 0;
int ret = select(0, NULL, &setW, &setE, &time_out);
if (ret <= 0)
{
// select() failed or connection timed out
closesock(&sock);
if (ret == 0)
WSASetLastError(WSAETIMEDOUT);
return false;
}
if (FD_ISSET(sock, &setE))
{
// connection failed
int err = 0;
getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, sizeof(err));
closesock(&sock);
WSASetLastError(err);
return false;
}
}
// connection successful
// put socked in blocking mode...
block = 0;
if (ioctlsocket(sock, FIONBIO, &block) == SOCKET_ERROR)
{
closesock(&sock);
return false;
}
return true;
}
Related
I created two win32 server c++ projects both will do similar task like listen for IPC connection from client. both will listen in different port numbers like 1000 and 2000, I'm able to connect first started application like 1000 or 2000 but not both, every second connection request will through timeout at client side.
Below I added my client and server code, I have two server applications with different port no (1000 and 2000) and two client applications which connect to 1000 and 2000 port server app.
Both server apps will go for listening mode but one only take connection request another will throw timeout at client application. if any suggestion please update your comments.
Client Code :
void Initialize()
{
WSADATA WSAData;
WSAStartup(MAKEWORD(2, 2), &WSAData);
}
SOCKET CloseSocket(SOCKET _Socket)
{
/*A shutdown() closes SOCK_STREAM sockets gracefully. Both processes can acknowledge that they are no longer sending. OR Disable sends and/or receives on a socket*/
shutdown(_Socket,SD_BOTH);
/*The closesocket function closes an existing socket.*/
closesocket(_Socket);
return _Socket = INVALID_SOCKET;
}
SOCKET Connect( SOCKET _Socket,
SOCKADDR_IN _Addres )
{
int connectResult = connect(_Socket,(struct sockaddr *)&_Addres,sizeof(_Addres));
if(connectResult == SOCKET_ERROR)
{
_Socket = CloseSocket(_Socket);
}
else if(connectResult == ETIMEDOUT)
{
_Socket = CloseSocket(_Socket);
}
return _Socket;
}
SOCKET ClientSocketPipline(SOCKET _Socket)
{
/*Socket types are defined in sys/socket.h. These types--SOCK_STREAM, SOCK_DGRAM, or SOCK_RAW--are supported by AF_INET and AF_UNIX. The following creates a stream socket in the Internet domain:*/
if ((_Socket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
return _Socket = CloseSocket(_Socket);
}
struct timeval timeout;
memset(&timeout,0,sizeof(timeout));
timeout.tv_sec = 2;
timeout.tv_usec = 0;
if ( setsockopt (_Socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) < 0 &&
setsockopt (_Socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0 )
{
return _Socket = CloseSocket(_Socket);
}
return _Socket;
}
void ClientConnectionCall()
{
SOCKET ConnectSocket;
ConnectSocket = INVALID_SOCKET;
ConnectSocket = ClientSocketPipline(ConnectSocket);
SOCKADDR_IN SocketAddres;
memset(&SocketAddres,0,sizeof(SocketAddres));
/*Convert IPv4 and IPv6 addresses from text to binary form*/
if(inet_pton(AF_INET,"192.160.1.1", &SocketAddres.sin_addr.s_addr)>0)
{
SocketAddres.sin_port = htons(1000); // and 2000
SocketAddres.sin_family = AF_INET;
ConnectSocket = Connect(ConnectSocket, SocketAddres);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
Initialize();
ClientConnectionCall();
return 0;
}
Server Code listener (Port no : 1000) :
SOCKET ServerClass::CloseSocket(SOCKET _Socket)
{
/*A shutdown() closes SOCK_STREAM sockets gracefully. Both processes can acknowledge that they are no longer sending. OR Disable sends and/or receives on a socket*/
shutdown(_Socket,SD_BOTH);
/*The closesocket function closes an existing socket.*/
closesocket(_Socket);
return _Socket = INVALID_SOCKET;
}
SOCKET ServerClass::Bind(SOCKET _Socket, SOCKADDR_IN _Address)
{
/*bind : Associate a local address with a socket.*/
if(::bind(_Socket,(struct sockaddr*)&_Address,sizeof(_Address)) == SOCKET_ERROR)
{
_Socket = CloseSocket(_Socket);
}
return _Socket;
}
SOCKET ServerClass::ServerSocketPipline(SOCKET _Socket,int _Type)
{
/*Socket types are defined in sys/socket.h. These types--SOCK_STREAM, SOCK_DGRAM, or SOCK_RAW--are supported by AF_INET and AF_UNIX. The following creates a stream socket in the Internet domain:*/
if ((_Socket = socket(AF_INET, _Type, 0)) < 0)
{
return _Socket = CloseSocket(_Socket);
}
int opt = 1;
/* Set socket keep connections alive */
if (setsockopt(_Socket,SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) == SOCKET_ERROR)
{
return _Socket = CloseSocket(_Socket);
}
return _Socket;
}
SOCKET ServerClass::CreateSocket(SOCKET _Socket, int _Port)
{
_Socket = INVALID_SOCKET;
_Socket = ServerSocketPipline(_Socket, SOCK_STREAM);
SOCKADDR_IN SocketAddres;
memset(&SocketAddres,0,sizeof(SocketAddres));
SocketAddres.sin_addr.s_addr = htonl(INADDR_ANY);
SocketAddres.sin_port = htons(_Port);
SocketAddres.sin_family = AF_INET;
//Associate a local address with a socket.
_Socket = Bind( _Socket, SocketAddres );
/*Establish a socket to listen for incoming connection*/
if(::listen(_Socket, 5) != SOCKET_ERROR)
{
//Socket listen success.
}
else
{
//Socket listen failed.
_Socket = SOCKET_ERROR;
}
return _Socket;
}
DWORD WINAPI ServerClass::SocketListener(LPVOID threadParam)
{
if(threadParam != NULL)
{
ServerClass *thisClass = (ServerClass *)threadParam;
SOCKET tempSocket = INVALID_SOCKET;
socklen_t addrlen = sizeof(struct sockaddr_in);
SOCKADDR_IN SocketAddres;
memset(&SocketAddres,0,sizeof(SocketAddres));
SocketAddres.sin_addr.s_addr = htonl(INADDR_ANY);
SocketAddres.sin_port = htons(1000);
SocketAddres.sin_family = AF_INET;
if(thisClass->m_BindSock != INVALID_SOCKET)
{
/*Accept a connection on a socket.*/
tempSocket = ::accept( thisClass->m_BindSock, (struct sockaddr*)&SocketAddres, &addrlen);
if(tempSocket != INVALID_SOCKET)
{
SetEvent(thisClass->m_SocketThreadHandle);
}
else
{
tempSocket = thisClass->CloseSocket(tempSocket);
SetEvent(thisClass->m_SocketThreadHandle);
}
}
}
return 0;
}
ServerClass::ServerMainCall(void)
{
Initialize();
m_BindSock = CreateSocket(m_BindSock,1000);
m_SocketThreadHandle = CreateThread(NULL, 0, SocketListener, this, 0, NULL);
WaitForSingleObject(m_SocketThreadHandle,INFINITE);
int msgboxID = MessageBox( NULL, L"Connection request received from first client", L"",
MB_ICONEXCLAMATION | MB_OK );
}
Server Code listener (Port no : 2000) :
SOCKET ServerClass::CloseSocket(SOCKET _Socket)
{
/*A shutdown() closes SOCK_STREAM sockets gracefully. Both processes can acknowledge that they are no longer sending. OR Disable sends and/or receives on a socket*/
shutdown(_Socket,SD_BOTH);
/*The closesocket function closes an existing socket.*/
closesocket(_Socket);
return _Socket = INVALID_SOCKET;
}
SOCKET ServerClass::Bind(SOCKET _Socket, SOCKADDR_IN _Address)
{
/*bind : Associate a local address with a socket.*/
if(::bind(_Socket,(struct sockaddr*)&_Address,sizeof(_Address)) == SOCKET_ERROR)
{
_Socket = CloseSocket(_Socket);
}
return _Socket;
}
SOCKET ServerClass::ServerSocketPipline(SOCKET _Socket,int _Type)
{
/*Socket types are defined in sys/socket.h. These types--SOCK_STREAM, SOCK_DGRAM, or SOCK_RAW--are supported by AF_INET and AF_UNIX. The following creates a stream socket in the Internet domain:*/
if ((_Socket = socket(AF_INET, _Type, 0)) < 0)
{
return _Socket = CloseSocket(_Socket);
}
int opt = 1;
/* Set socket keep connections alive */
if (setsockopt(_Socket,SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) == SOCKET_ERROR)
{
return _Socket = CloseSocket(_Socket);
}
return _Socket;
}
SOCKET ServerClass::CreateSocket(SOCKET _Socket, int _Port)
{
_Socket = INVALID_SOCKET;
_Socket = ServerSocketPipline(_Socket, SOCK_STREAM);
SOCKADDR_IN SocketAddres;
memset(&SocketAddres,0,sizeof(SocketAddres));
SocketAddres.sin_addr.s_addr = htonl(INADDR_ANY);
SocketAddres.sin_port = htons(_Port);
SocketAddres.sin_family = AF_INET;
//Associate a local address with a socket.
_Socket = Bind( _Socket, SocketAddres );
/*Establish a socket to listen for incoming connection*/
if(::listen(_Socket, 5) != SOCKET_ERROR)
{
//Socket listen success.
}
else
{
//Socket listen failed.
_Socket = SOCKET_ERROR;
}
return _Socket;
}
DWORD WINAPI ServerClass::SocketListener(LPVOID threadParam)
{
if(threadParam != NULL)
{
ServerClass *thisClass = (ServerClass *)threadParam;
SOCKET tempSocket = INVALID_SOCKET;
socklen_t addrlen = sizeof(struct sockaddr_in);
SOCKADDR_IN SocketAddres;
memset(&SocketAddres,0,sizeof(SocketAddres));
SocketAddres.sin_addr.s_addr = htonl(INADDR_ANY);
SocketAddres.sin_port = htons(2000);
SocketAddres.sin_family = AF_INET;
if(thisClass->m_BindSock != INVALID_SOCKET)
{
/*Accept a connection on a socket.*/
tempSocket = ::accept( thisClass->m_BindSock, (struct sockaddr*)&SocketAddres, &addrlen);
if(tempSocket != INVALID_SOCKET)
{
SetEvent(thisClass->m_SocketThreadHandle);
}
else
{
tempSocket = thisClass->CloseSocket(tempSocket);
SetEvent(thisClass->m_SocketThreadHandle);
}
}
}
return 0;
}
ServerClass::ServerMainCall(void)
{
Initialize();
m_BindSock = CreateSocket(m_BindSock,2000);
m_SocketThreadHandle = CreateThread(NULL, 0, SocketListener, this, 0, NULL);
WaitForSingleObject(m_SocketThreadHandle,INFINITE);
int msgboxID = MessageBox( NULL,L"Connection request received from second client",L"",
MB_ICONEXCLAMATION | MB_OK);
}
Finally found the answer to the problem. The issue is because of the firewall blocking at server machine side. After disable it, things started working, for more details please go to the below link:
What can be the reasons of connection refused errors?
My udp server needs to generate a temporary unused port for each client, so I bind with zero-port to get it. But the bind function sometimes returns a used port, so client A received data which should have been sent to client B.
int _fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (_fd < 0)
{
return false;
}
INT reuse = 1;
INT ret = setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
if (ret == -1)
{
return false;
}
sockaddr_in local_addr;
int addr_len = sizeof(sockaddr_in);
local_addr.sin_family = AF_INET;
local_addr.sin_addr.s_addr = inet_addr(ip.c_str());
if (::bind(_fd, (sockaddr *) &local_addr, sizeof(local_addr)) == -1)
{
return false;
}
if (::getsockname(_fd, (sockaddr*)&local_addr, &addr_len) == -1)
{
return false;
}
What I'm trying to do is a forking proxy that deals HTTP(S) connections: while GET (without SSL) requests are successfully executed and the contents are delivered to the client, when it comes to CONNECT method things are not going well, since connect()ing to the remote server may not immediately succeeds: in fact, it nevers succeeds.
I tried for a non blocking socket connected to the remote server, so I can see if connect() goes immediately or takes some time: in the second case, I'd call select() to see when the remote server is ready to send data to me: yet, connect() never connects.
Here's my proxy main() code:
int main(int argc, char *argv[]) {
// ClientManager.cpp is described below
ClientManager cm;
//listening on port given by argv
if (cm.startListeningForClient(listening_port)) {
while(true) {
int new_client_socket = cm.acceptConnectionFromClient();
if (new_client_socket >= 0) {
cm.forkAndManageClient();
}
else {
perror("accept error");
}
}
} else {
perror("Error on start listening");
}
return EXIT_SUCCESS;
}
Now follows, with some omissis not involved with my issue, ClientManager.cpp, whose functions are called in main() above:
ClientManager::ClientManager() {
sockfd_client = -1; // socket connected to client
new_sockfd_client = -1; // socket accepting connection from client
sockfd_server = -1; // socket connected to remote server
}
// error controls omitted
bool ClientManager::startListeningForClient(int port) {
struct sockaddr_in serv_addr;
bzero((char*)&serv_addr,sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(port);
serv_addr.sin_addr.s_addr=INADDR_ANY;
sockfd_client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
bind(sockfd_client,(struct sockaddr*)&serv_addr, sizeof(serv_addr));
listen(sockfd_client, 50);
return true;
}
// error controls omitted
int ClientManager::acceptConnectionFromClient(void) {
struct sockaddr_in cli_addr;
unsigned int clilen;
bzero((char*)&cli_addr, sizeof(cli_addr));
clilen = sizeof(cli_addr);
new_sockfd_client = accept(sockfd_client, (struct sockaddr*)&cli_addr, &clilen);
return new_sockfd_client;
}
int ClientManager::forkAndManageClient() {
// getRequestFromClient: the method below receives requests from
// clients and parses the infos I need (i.e. what method,
// hostname of remote server to be resolved, its port, ...)
getRequestFromClient();
// managing the HTTP(S) request by the child process
int pid = fork();
if (pid < 0) {
perror("ERROR on fork");
}
else if (pid > 0) {
// parent process
// do nothing
}
else {
// close immediately the client socket used for accepting new connections from the parent process
close (sockfd_client);
if (!manageRequest()) {
perror("Error managing request from client");
}
// close the connection from the client
close (new_sockfd_client);
new_sockfd_client = -1;
// the child process will terminate now
_exit(EXIT_SUCCESS);
}
return pid;
}
// now the problematic method...
bool ClientManager::manageRequest(void) {
// if this is a CONNECT request
if (rm.isCONNECT()) {
struct sockaddr_in remote_server;
int conn_res;
remote_server.sin_family = AF_INET;
remote_server.sin_addr.s_addr = rm.getServerAddr();
remote_server.sin_port = rm.getServerPort();
fd_set fdset;
struct timeval tv;
sockfd_server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// make socket not blocking
int flags = fcntl(sockfd_server, F_GETFL, 0);
flags = flags | O_NONBLOCK;
if (fcntl(sockfd_server, F_SETFL, flags) == -1) {
perror("FCNTL:");
}
printf("CONNECT set socket to non-blocking mode\n");
conn_res = connect(sockfd_server, (struct sockaddr *)&remote_server, sizeof(struct sockaddr_in));
printf("AFTER CONNECT()\n");
if (conn_res < 0) {
if (errno != EINPROGRESS) {
printf("CONNECT: connect() failed, quitting\n");
return false;
}
}
printf("CONNECT connection is taking place...\n");
// connected immediately
if (conn_res == 0) {
printf("CONNECT connected OK!\n");
goto CONNECTED;
}
FD_ZERO(&fdset);
FD_SET(sockfd_server, &fdset);
tv.tv_sec = 5; // tried 5, 20, 60 seconds, but it always times out
tv.tv_usec = 0;
printf("CONNECT attempting select()\n");
if (select(sockfd_server+1, NULL, &fdset, NULL, &tv) == 0) {
errno = ETIMEDOUT;
close(sockfd_server);
sockfd_server = -1;
return false;
}
if (FD_ISSET(sockfd_server, &fdset)) {
int so_error;
socklen_t len = sizeof so_error;
if (getsockopt(sockfd_server, SOL_SOCKET, SO_ERROR, &so_error, &len) < 0) {
return false;
}
} else {
printf("sockfd_server not set\n");
}
CONNECTED:
fcntl(sockfd_server, F_SETFL, flags &~ O_NONBLOCK);
// yeah, now I will start to deal the HTTPS flow in both directions
return true;
}
}
It does manage setting socket to non blocking mode, and to print CONNECT connection is taking place..., but it always returns Error managing request from client: Connection timed out.
I apologize for posting miles of LOC, but this is what drives me crazy since days, and after reading posts, tutorial and guides, I really don't know what to do.
It connects now to every site which requires an HTTPS connection!
Proper error checking and following closing of socket descriptors were missing. Here's my code:
bool ClientManager::manageRequest(void) {
if (rm.isCONNECT()) {
struct sockaddr_in remote_server, local_bind;
int conn_res, select_res;
memset(&remote_server, 0, sizeof(remote_server));
remote_server.sin_family = AF_INET;
remote_server.sin_addr.s_addr = rm.getServerAddr();
remote_server.sin_port = rm.getServerPort();
memset(&local_bind, 0, sizeof(local_bind));
local_bind.sin_family = AF_INET;
local_bind.sin_addr.s_addr = htonl(INADDR_ANY);
local_bind.sin_port = htons(0);
fd_set rdset, wrset;
struct timeval tv;
sockfd_server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockfd_server < 0) {
perror("socket: ");
}
if(!setNonBlocking(sockfd_server))
perror("fcntl");
debug_green("CONNECT set socket to non-blocking mode\n");
bind(sockfd_server, (struct sockaddr*) &local_bind, sizeof(local_bind));
conn_res = connect(sockfd_server, (struct sockaddr *)&remote_server, sizeof(struct sockaddr_in));
// The socket is nonblocking and the connection cannot be completed immediately
// check for EINPROGRESS
if ((conn_res == -1) && (errno != EINPROGRESS)) {
FD_ZERO(&rdset);
FD_SET(sockfd_server, &rdset);
wrset = rdset;
tv.tv_sec = 0;
tv.tv_usec = 0;
debug_yellow("CONNECT attempting select()\n");
do {
select_res = select(sockfd_server+1, &rdset, &wrset, NULL, &tv);
} while ((select_res == -1) && (errno == EINTR));
if ((!FD_ISSET(sockfd_server, &rdset)) && ((!FD_ISSET(sockfd_server, &wrset)))) {
debug_red("SELECT sockfds not responding\n");
close(sockfd_server);
sockfd_server = -1;
return false;
}
conn_res = connect(sockfd_server, (struct sockaddr *)&remote_server, sizeof(struct sockaddr_in));
if (conn_res == -1) {
if(errno == EISCONN)
printf ("connect(): connections already existing, OK\n");
else {
printf("connect() for safety check: connection NOT successfull\n");
close(sockfd_server);
sockfd_server = -1;
return false;
}
}
printf("connection OK\n");
fflush(stdout);
} else {
debug_green("Connection immediately OK\n");
fflush(stdout);
}
if (!setBlocking(sockfd_server)) {
perror("FCNTL:");
}
debug_green("CONNECT set socket back to blocking mode\n");fflush(stdout);
}
return true;
}
Functions setting blocking or non blocking socket:
bool ClientManager::setNonBlocking(int sockfd) {
printf("setting non block socket\n"); fflush(stdout);
int flags;
if ((flags = fcntl(sockfd, F_GETFL, 0)) < 0)
return false;
flags |= O_NONBLOCK;
if (fcntl(sockfd, F_SETFL, flags) < 0)
return false;
return true;
}
bool ClientManager::setBlocking(int sockfd) {
printf("setting block socket\n"); fflush(stdout);
int flags;
if ((flags = fcntl(sockfd, F_GETFL, 0)) < 0)
return false;
flags &= (~O_NONBLOCK);
if (fcntl(sockfd, F_SETFL, flags) < 0)
return false;
return true;
}
Debug functions:
#define DEFAULTCOLOR "\033[0m"
#define RED "\033[22;31m"
#define YELLOW "\033[1;33m"
#define GREEN "\033[0;0;32m"
#define debug_red(...) std::cout << RED << __VA_ARGS__ << DEFAULTCOLOR; fflush(stdout);
#define debug_yellow(...) std::cout << YELLOW << __VA_ARGS__ << DEFAULTCOLOR; fflush(stdout);
#define debug_green(...) std::cout << GREEN << __VA_ARGS__ << DEFAULTCOLOR; fflush(stdout);
I have a server socket accepting client socket connections. Accept is in a thread
socket creation
int ServerSocket::CreateSocket(int port)
{
listenfd = 0;
struct sockaddr_in serv_addr;
unsigned long iMode = 1;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(port);
ioctlsocket(listenfd, FIONBIO, &iMode);
if (bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
{
return 0;
}
if (listen(listenfd, 20) < 0)
{
return 0;
}
return listenfd;
}
Socket Accept
void ServerSocket::AcceptClients_1(void * p)
{
struct sockaddr_in cli_addr;
// get a pointer to the ServerSocket object
ServerSocket * pThis = (ServerSocket *)p;
int iResult, cli_len;
cli_len = sizeof(cli_addr);
struct timeval tv = { 0, 1000 };
SOCKET s = pThis->GetSocket();
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(s, &rfds);
while (!pThis->ShutDownRequested)
{
iResult = select(s+1, &rfds, (fd_set *) 0, (fd_set *) 0, &tv);
if(iResult > 0)
{
// never comes here
SOCKET sclient = accept(s, (struct sockaddr *)&cli_addr,
&cli_len);
}
else if (iResult == 0) /// timeout
{
continue;
}
// error comes here are going to accept 2nd time
DWORD dwError = GetLastError();
return;
}
}
The code comes on select(). Returns 0 the first time but second time always returns -1 with error 10022. I don't understand why. Please help.
Make sure your pThis->GetSocket() is correctly returning the listenfd. Also, you should reinitialize cli_len = sizeof(cli_addr); before each call to accept (it's a value-result argument).
iResult=0 does not always mean timeout, for non-blocking sockets, you need to check WSAGetLastError and deal with some error codes, for example WSAEWOULDBLOCK means you need to wait next event on this socket.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx
I use following code to check if a port is available or not:
bool ClassA::CheckPortTCP(short int dwPort , char *ipAddressStr)
{
struct sockaddr_in client;
int sock;
client.sin_family = AF_INET;
client.sin_port = htons(dwPort);
client.sin_addr.S_un.S_addr = inet_addr(ipAddressStr);
sock = (int) socket(AF_INET, SOCK_STREAM, 0);
int result = connect(sock, (struct sockaddr *) &client,sizeof(client));
// change to result == 0 -> failure in writing code too quick ;-)
if (result = 0) return true; // port is active and used
else return false;
}
The problem is if the port is opened but not connected the check failed! How can I easily examine that the port is available (not listening, not connected)?
e.g. port 21111 (output of netstat) -> my function doesn't recognize that the port is not free
TCP 0.0.0.0:21111 xxxxDUMMYxxxx:0 LISTENING
Thx
You have two errors: The first is that in the if statement you assign zero to result. The other is that connect returns -1 on failure to connect, and a non-negative value if it manages to connect.
There is also a problem that if you manage to connect, you don't close that connection.
the line client.sin_addr.S_un.S_addr = inet_addr(ipAddressStr); can not work for me. change it to:
bool CheckPortTCP(short int dwPort, char *ipAddressStr)
{
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR) {
wprintf(L"WSAStartup function failed with error: %d\n", iResult);
return false;
}
struct sockaddr_in client;
int sock;
client.sin_family = AF_INET;
client.sin_port = htons(dwPort);
client.sin_addr.s_addr = inet_addr(ipAddressStr);
sock = (int)socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET) {
wprintf(L"ERROR: Socket function failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return false;
}
printf("INFO: Checking Port : %s:%d\n", ipAddressStr, dwPort);
int result = connect(sock, (struct sockaddr *) &client, sizeof(client));
if (result == SOCKET_ERROR) {
printf("ERROR: %s", WSAGetLastError());
WSACleanup();
return false;
}
else
{
WSACleanup();
closesocket(sock);
return true;
}
}