I have created a Socket class, everything was working perfect earlier. And just now every time I try to bind the socket server-side, it throws a bind error with message "Address already in use" while the port is free.
I am using macOS.
Should i use AF_INET or AF_UNIX?
This some of the code for the socket & bind.
// socket object class.
class Socket {
public:
int sock;
string address;
string port;
struct addrinfo address_info;
bool connected;
// initialize.
public:
Socket(string address__ = "", string port__ = "", bool initialize = false, int domain = -999, int type = -999, int protocol = -999) {
address = address__;
port = port__;
connected = false;
if (domain == -999) {
//domain = AF_INET;
domain = AF_UNIX;
//domain = 2;
} if (type == -999) {
type = SOCK_STREAM;
} if (protocol == -999) {
protocol = 0;
}
memset(&address_info, 0, sizeof address_info);
address_info.ai_family = domain;
address_info.ai_socktype = type;
address_info.ai_protocol = protocol;
if (initialize) {
print("Initialize socket...");
sock = socket(address_info.ai_family, address_info.ai_socktype, address_info.ai_protocol);
if (sock < 0) {
int e = errno;
string error = "BindError: Unable to initialize the socket.";
print(error);
throw BindError(error);
}
}
}
// bind server.
public:
int bind() {
int optVal = 1;
set_opt(SOL_SOCKET, SO_REUSEADDR, &optVal);
if (address_info.ai_family == AF_UNIX) {
//print("UNIX");
struct sockaddr_un addr;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, address.c_str(), sizeof(addr.sun_path)-1);
int status = ::bind(sock, (struct sockaddr*)&addr, sizeof(addr));
if (status < 0) {
int e = errno;
string error = "BindError: Unable to bind with "+address+":"+port+" - "+strerror(e)+".";
print(error);
throw BindError(error);
}
return status;
}
//print("NON UNIX");
int status;
struct addrinfo *res;
address_info.ai_flags = AI_PASSIVE;
if ((status = getaddrinfo(address.c_str(), port.c_str(), &address_info, &res)) != 0) {
throw std::runtime_error("GetInfoError"); // gai_strerror(errno)
}
address_info.ai_addrlen = res->ai_addrlen;
address_info.ai_addr = res->ai_addr;
freeaddrinfo(res);
int max_attempts = 1;
for (int attempt = 0; attempt < max_attempts; ++ attempt) {
status = ::bind(sock, address_info.ai_addr, address_info.ai_addrlen);
if (status >= 0) {
break;
}
if (status < 0 && attempt >= max_attempts - 1) {
//cout << sock << " - " << address_info.ai_addr << " - " << address_info.ai_addrlen << " - " << "\n";
int e = errno;
string error = "BindError: Unable to bind with "+address+":"+port+" - "+strerror(e)+".";
print(error);
throw BindError(error);
}
}
return status;
}
};
Does anyone have an idea how to fix this?
Related
I am developing a DTLS server and client. But there is no handshake between them.
PS I made a cut from the project in order to reduce the amount of code. If you forgot something - do not kick ...
a common part
static int dtls_verify_callback(int ok, X509_STORE_CTX* ctx) {
return ok;
}
static int generate_cookie(SSL* ssl, unsigned char* cookie, unsigned int* cookie_len) {
unsigned int i;
for (i = 0; i < COOKIE_LEN; i++, cookie++)
*cookie = i;
*cookie_len = COOKIE_LEN;
return 1;
}
static int verify_cookie(SSL* ssl,
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
const
#endif
unsigned char* cookie,
unsigned int cookie_len) {
unsigned int i;
if (cookie_len != COOKIE_LEN)
return 0;
for (i = 0; i < COOKIE_LEN; i++, cookie++) {
if (*cookie != i)
return 0;
}
return 1;
}
Server side
int main() {
int iTimeout = 1000;
ADDRINFOW* pAddressInfo;
ADDRINFOW AddressHints;
WSADATA WinsockData;
LPCWSTR lpwszAddress = L"";
SOCKET socket;
union {
struct sockaddr_storage ss;
struct sockaddr_in s4;
struct sockaddr_in6 s6;
} server_addr, client_addr;
const TIMEVAL Timeout = { iTimeout / 1000, (iTimeout % 1000) * 1000 };
if (1 != OPENSSL_init_ssl(0
| OPENSSL_INIT_NO_LOAD_CONFIG
| OPENSSL_INIT_ASYNC
| OPENSSL_INIT_ENGINE_DYNAMIC
| OPENSSL_INIT_ENGINE_ALL_BUILTIN
| OPENSSL_INIT_NO_ATEXIT
| OPENSSL_INIT_LOAD_SSL_STRINGS
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS
, nullptr))
{
return 1;
}
WSAStartup(MAKEWORD(2, 2), &WinsockData);
auto ctx = unique_ptr_c<SSL_CTX>(SSL_CTX_new(DTLS_server_method()), SSL_CTX_free);
auto cert_store = unique_ptr_c<X509_STORE>(X509_STORE_new(), X509_STORE_free);
X509_STORE_load_locations(cert_store.get(), "certs/ca-cert.pem", nullptr);
SSL_CTX_set1_verify_cert_store(ctx.get(), cert_store.get());
if (!SSL_CTX_use_certificate_chain_file(ctx.get(), "certs/server-cert.pem"))
{
ERR_print_errors_fp(stderr);
}
if (!SSL_CTX_use_PrivateKey_file(ctx.get(), "certs/server-key.pem", SSL_FILETYPE_PEM))
{
ERR_print_errors_fp(stderr);
}
if (!SSL_CTX_check_private_key(ctx.get()))
{
ERR_print_errors_fp(stderr);
}
SSL_CTX_set_verify(ctx.get(), SSL_VERIFY_PEER, dtls_verify_callback);
SSL_CTX_set_read_ahead(ctx.get(), 1);
SSL_CTX_set_cookie_generate_cb(ctx.get(), generate_cookie);
SSL_CTX_set_cookie_verify_cb(ctx.get(), verify_cookie);
memset(&AddressHints, 0, sizeof(AddressHints));
AddressHints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
AddressHints.ai_family = AF_UNSPEC;
AddressHints.ai_socktype = SOCK_DGRAM;
AddressHints.ai_protocol = 0;
iResult = GetAddrInfoW(lpwszAddress, 12345, &AddressHints, &pAddressInfo);
if (0 != iResult)
{
}
else
{
for (const ADDRINFOW* pCurrentAddressInfo = pAddressInfo; nullptr != pCurrentAddressInfo; pCurrentAddressInfo = pCurrentAddressInfo->ai_next)
{
socket = socket(pCurrentAddressInfo->ai_family, pCurrentAddressInfo->ai_socktype, pCurrentAddressInfo->ai_protocol);
if (INVALID_SOCKET == CurrentSocket) { continue; }
if (SOCKET_ERROR == bind(CurrentSocket, pCurrentAddressInfo->ai_addr, static_cast<int>(pCurrentAddressInfo->ai_addrlen)))
{
(void)closesocket(CurrentSocket);
continue;
}
if (SOCKET_ERROR == setsockopt(CurrentSocket, SOL_SOCKET, SO_SNDTIMEO, reinterpret_cast<const char*>(&iTimeout), sizeof(iTimeout))) { }
break;
}
}
for (;;)
{
if (SOCKET_ERROR == select(0, &socket, nullptr, nullptr, &Timeout)) {}
memset(&client_addr, 0, sizeof(struct sockaddr_storage));
auto bio = BIO_new_dgram(socket, BIO_NOCLOSE);
auto ssl = unique_ptr_c<SSL>(SSL_new(ctx.get()), SSL_close_and_free);
SSL_set_bio(ssl.get(), bio, bio);
SSL_set_options(ssl.get(), SSL_OP_COOKIE_EXCHANGE);
while (iResult <= 0) {
iResult = DTLSv1_listen(ssl.get(), (BIO_ADDR*)&client_addr);
if (iResult <= 0) { }
}
BIO_set_fd(SSL_get_rbio(ssl.get()), socket, BIO_NOCLOSE);
BIO_ctrl(SSL_get_rbio(ssl.get()), BIO_CTRL_DGRAM_SET_CONNECTED, 0, &client_addr);
iResult = SSL_accept(ssl.get());
if (iResult != 1) {
printf("%s\n", ERR_error_string(ERR_peek_last_error(), NULL));
printf("%s\n", ERR_error_string(ERR_get_error(), buf));
}
else
{
// I didn't cut the code further, since it never goes here
}
}
}
Client side
int main() {
ADDRINFOW AddressHints;
SOCKET ClientSocket = INVALID_SOCKET;
memset(&AddressHints, 0, sizeof(AddressHints));
AddressHints.ai_family = AF_UNSPEC;
AddressHints.ai_socktype = SOCK_DGRAM;
AddressHints.ai_protocol = 0;
int iResult = GetAddrInfoW(lpwszHost, wszPort, &AddressHints, &pAddressInfo);
if (0 != iResult)
{
}
else
{
unique_ptr_c<SSL_CTX> ctx;
unique_ptr_c<SSL> ssl;
BIO* bio;
if (1 != OPENSSL_init_ssl(0
| OPENSSL_INIT_NO_LOAD_CONFIG
| OPENSSL_INIT_ASYNC
| OPENSSL_INIT_ENGINE_DYNAMIC
| OPENSSL_INIT_ENGINE_ALL_BUILTIN
| OPENSSL_INIT_NO_ATEXIT
| OPENSSL_INIT_LOAD_SSL_STRINGS
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS
, nullptr))
{
return 1;
}
ctx = unique_ptr_c<SSL_CTX>(SSL_CTX_new(DTLS_client_method()), SSL_CTX_free);
auto cert_store = unique_ptr_c<X509_STORE>(X509_STORE_new(), X509_STORE_free);
X509_STORE_load_locations(cert_store.get(), "certs/ca-cert.crt", nullptr);
SSL_CTX_set1_verify_cert_store(ctx.get(), cert_store.get());
iResult = SSL_CTX_use_certificate_chain_file(ctx.get(), "certs/client-cert.pem");
if (!iResult)
{
ERR_print_errors_fp(stderr);
}
iResult = SSL_CTX_use_PrivateKey_file(ctx.get(), "certs/client-key.pem", SSL_FILETYPE_PEM);
if (!iResult)
{
ERR_print_errors_fp(stderr);
}
if (!SSL_CTX_check_private_key(ctx.get()))
{
ERR_print_errors_fp(stderr);
}
SSL_CTX_set_verify(ctx.get(), SSL_VERIFY_PEER, dtls_verify_callback);
SSL_CTX_set_read_ahead(ctx.get(), 1);
SSL_CTX_set_cookie_generate_cb(ctx.get(), generate_cookie);
SSL_CTX_set_cookie_verify_cb(ctx.get(), verify_cookie);
ssl = unique_ptr_c<SSL>(SSL_new(ctx.get()), SSL_close_and_free);
for (pCurrentAddressInfo = pAddressInfo; nullptr != pCurrentAddressInfo; pCurrentAddressInfo = pCurrentAddressInfo->ai_next)
{
ClientSocket = socket(pCurrentAddressInfo->ai_family, pCurrentAddressInfo->ai_socktype, pCurrentAddressInfo->ai_protocol);
if (INVALID_SOCKET == ClientSocket)
{
continue;
}
iResult = connect(ClientSocket, pCurrentAddressInfo->ai_addr, static_cast<int>(pCurrentAddressInfo->ai_addrlen));
if (SOCKET_ERROR == iResult)
{
}
else
{
break;
}
if (SOCKET_ERROR == closesocket(ClientSocket))
{
}
}
if (nullptr != pCurrentAddressInfo)
{
if (SOCKET_ERROR == setsockopt(ClientSocket, SOL_SOCKET, SO_RCVTIMEO, reinterpret_cast<const char*>(&iTimeout), sizeof(iTimeout)))
{
iResult = WSAGetLastError();
}
else
{
bio = BIO_new_dgram(ClientSocket, BIO_NOCLOSE);
BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_CONNECTED, 0, remote_address.get());
SSL_set_bio(ssl.get(), bio, bio);
iResult = SSL_connect(ssl.get()); // Trying 5 handshakes fails with an SSL_ERROR_SYSCALL error
if (iResult <= 0) {
char buf[BUFFER_SIZE];
//print_errors_stderr();
ERR_print_errors_fp(stderr);
printf("%s\n", ERR_error_string(ERR_peek_last_error(), NULL));
printf("%s\n", ERR_error_string(ERR_get_error(), buf));
switch (SSL_get_error(ssl.get(), iResult)) {
...
case SSL_ERROR_SYSCALL:
ERR_print_errors_fp(stderr);
DBG_MSG((DBG_ERR, L"DTLSClient::Send: SSL_connect failed with SSL_ERROR_SYSCALL"));
break;
...
}
fprintf(stderr, "%s\n", ERR_error_string(ERR_get_error(), NULL));
ERR_print_errors_fp(stderr);
}
else
{
// I didn't cut the code further, since it never goes here
}
}
// Close the socket
if (SOCKET_ERROR == closesocket(ClientSocket))
{
}
}
}
}
The client tries 5 times to make a handshake with the server but it doesn't work.
An error occurs from the client side on the line iResult = SSL_connect(ssl.get()) - an error occurs:
error:00000000:lib(0)::reason(0)
ERR: DTLSClient::Send: SSL_connect failed with SSL_ERROR_SYSCALL
An error occurs on the server at the line iResult = SSL_accept(ssl.get()) - with the error:
SSL_accept: No error
error:00000000:lib(0)::reason(0)
Based on traffic
enter image description here
Client sends - Client Hello
The server replies to this - Hello verify Request
And then the client tries to answer something back. Now I don't know what to do next. Are there any ideas?
I tried to do it as in the examples from OpenLL and other examples on github.
I'm trying to make a simple heartbeat check from client to server and vice-versa, if connection on either is broken off unexpectedly it prints a message and calls closesocket.
I spent 8 hours on this and it still isn't acceptable to my mentor. Right now I got something that works, but if breakpoint is placed before while loop and connected client is forcefully closed, trying to go past breakpoint causes crash when it should break the loop and write out error.
Server side code:
int main(int argc, char *argv[])
{
SOCKET s, sa;
WSAData oWSAData;
WORD wVersion = 0x0001;
WSAStartup(wVersion, &oWSAData);
s = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in srv_address;
memset(&srv_address, 0, sizeof(srv_address));
srv_address.sin_family = AF_INET;
srv_address.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
srv_address.sin_port = htons(1099);
bind(s, (sockaddr*) &srv_address, sizeof(srv_address));
int l = listen(s, 10);
if (l < 0)
printf("Listen error\n");
else
{
printf("Listen OK. Listening on port %u\n",
htons(srv_address.sin_port));
sa = accept(s, NULL, NULL);
while (true)
{
char buffer[1000];
int nRecvLen = recv(sa, buffer, 999, 0);
buffer[nRecvLen] = '\0';
int r = recv(sa, NULL, 0, 0);
if (r == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET)
{
printf("Konekcija je naglo prekinuta!\n");
break;
}
else
{
if (nRecvLen > 0)
{
for (int i = 0; i < nRecvLen; i++)
{
cout << buffer[i];
}
}
}
}
closesocket(sa);
closesocket(s);
}
WSACleanup();
return 0;
}
and client side:
int main()
{
SOCKET s;
WSAData oWSAData;
WORD wVersion = 0x0001;
WSAStartup(wVersion, &oWSAData);
s = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in srv_address;
memset(&srv_address, 0, sizeof(srv_address));
srv_address.sin_family = AF_INET;
srv_address.sin_addr.S_un.S_un_b.s_b1 = xxx;
srv_address.sin_addr.S_un.S_un_b.s_b2 = xxx;
srv_address.sin_addr.S_un.S_un_b.s_b3 = x;
srv_address.sin_addr.S_un.S_un_b.s_b4 = xxx;
srv_address.sin_port = htons(1099);
int c = connect(s, (sockaddr*) &srv_address, sizeof(srv_address));
if (c < 0)
{
printf("Connection error\n");
cout << (WSAGetLastError());
}
else
{
string l = "Heartbeat\n";
int p = l.size();
char buff[1000];
strcpy_s(buff, l.c_str());
printf("Connected\n");
while (true)
{
if (send(s, buff, p, 0) > 0)
{
Sleep(1000);
}
else
{
printf("Konekcija je naglo prekinuta\n");
shutdown(s, SD_BOTH);
closesocket(s);
break;
}
}
WSACleanup();
return 0;
}
}
I having issues creating an echo program using socket programming. I do not have any error coded appear when I run the socket(), bind(), and listen() command. All of them return an integer, value 3. The part that is causing the issue in the accept() command. To test this program, I have ran the executable as a background process and run telnet to test the socket connection. The program is freezing at the accept() command. Can anyone help?
// Include all of the headers required
#include "echo_s.h"
// simple logger
#include "log.h"
// ***
// Class ClientConnection
// - created to help simply methods and functions used to create TCP connection
// for this program to work
class ClientConnection {
public:
void createSocket();
void setupAddress();
void bindSocket();
void listenSocket();
void waitingConnection();
int processConnection(int connection);
private:
int sock = -1; // file descriptor for the server
int lst = -1; // file descriptor for the listener
struct sockaddr_in
{
short family; // address family
u_short port; // port number
struct in_addr sin_addr; // internet address
char sin_zero[8];
};
struct sockaddr_in servAddr; // struct needed for the server addr
struct sockaddr_in clientAddr; // struct needed for the listener addr
char buffer[256];
};
Log* logger = new Log();
// ***
// main ()
// - sets up the socket and accepts new connection until CLOSE or QUIT
int main (int argc, char *argv[])
{
// Process the command arguments
int opt = 0;
ClientConnection client;
while ((opt = getopt(argc, argv, "v")) != -1)
{
switch (opt)
{
case 'v':
logger->setLogger(true);
logger->printLog("Verbose Action captured");
break;
case ':':
case '?':
default:
std::cout<< "Invalid option: " << argv[0] << std::endl;
exit(-1);
}
}
// create the socket
client.createSocket();
// set up socket address
client.setupAddress();
// bind socket
client.bindSocket();
// listen socket
client.listenSocket();
// Wait for the connection with the accept call
client.waitingConnection();
}
void ClientConnection::createSocket ()
{
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
logger->printLog ("Error opening socket");
exit (-1);
}
else
{
logger->printLog("Socket was created");
logger->printLog("Socket info: " + std::to_string(sock));
}
}
void ClientConnection::setupAddress ()
{
// define the struct
srand(time(NULL));
int port = (rand() % 10000 + 1024);
// zero the whole struct
bzero((char *)&servAddr, sizeof(servAddr));
// Fill in the struct with the information need for the address of the host
servAddr.family = AF_INET;
servAddr.sin_addr.s_addr = INADDR_ANY;
servAddr.port = htons(port);
logger->printLog("Address has been created for socket");
}
void ClientConnection::bindSocket ()
{
int bindSuccess = 0;
int attempts = 0;
std::string errorString;
if (bind(sock, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0)
{
errorString = strerror(errno);
logger->printLog("bind() failed: " + errorString);
exit(-1);
}
else
{
logger->printLog("bind() successful");
logger->printLog("Bind() function returned: " + std::to_string(sock));
std::cout << "Port number: " << servAddr.port << std::endl;
}
}
void ClientConnection::listenSocket ()
{
int listenSocket = 5;
std::string errorString;
if (listen(sock, listenSocket) < 0)
{
errorString = strerror(errno);
logger->printLog("listen() failed: " + errorString);
exit(-1);
}
else
{
logger->printLog("listen() successful");
logger->printLog("listen() fucntion returns: " + std::to_string(sock));
}
}
void ClientConnection::waitingConnection ()
{
logger->printLog("Attempting accept()");
int quit = -1;
int attempts = 0;
socklen_t sizeClient = sizeof(clientAddr);
while(quit == -1)
{
logger->printLog("Inside while loop");
//lst = accept(sock, (struct sockaddr *) &servAddr, sizeof(servAddr));
lst = accept(sock, (struct sockaddr *) NULL, NULL);
logger->printLog("accept() function reurns: " + std::to_string(lst));
if (lst < 0)
{
std::string errorString = strerror(errno);
logger->printLog(errorString);
attempts++;
exit(-1);
}
else
{
logger->printLog("accept() successful");
quit = processConnection(lst);
}
}
}
int ClientConnection::processConnection(int connection)
{
std::cout << "connection made. TEST" << std::endl;
int n = 0;
if ((n = read(connection, buffer, 255)) < 0)
{
logger->printLog("Error reading data");
}
else
{
std::string message = buffer;
logger->printLog(message);
if (message.find("QUIT"))
{
close(connection);
return 1;
}
if (message.find("CLOSE"))
{
close(connection);
return 0;
}
n = write(connection, buffer, sizeof(buffer));
}
return 0;
}
`
I won't post all of the generic socket-code -- unless requested, then no problem.
I listen for connections on an already setup socket:
int
NetworkConnection::ListenForConnections()
{
char s[INET6_ADDRSTRLEN];
fcntl(socketFd, F_SETFL, O_NONBLOCK);
if (listen(socketFd, 15) == -1) {
perror("listen");
exit(1);
}
// sigAction.sa_handler = sigchld_handler; // reap all dead processes
// sigemptyset(&sigAction.sa_mask);
// sigAction.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sigAction, NULL) == -1) {
perror("sigaction");
exit(1);
}
printf("server: waiting for connections...\n");
sin_size = sizeof theirAddress;
int new_fd = accept(socketFd, (struct sockaddr *)&theirAddress, &sin_size);
if (new_fd == -1) {
perror("accept");
return 1;
}
inet_ntop(theirAddress.ss_family,
get_in_addr((struct sockaddr *)&theirAddress),
s, sizeof s);
printf("server: got connection from %s\n", s);
NodeConnection nc = NodeConnection();
char ipstr[INET6_ADDRSTRLEN];
getpeername(new_fd, (struct sockaddr*)&theirAddress, &sin_size);
struct sockaddr_in *soc = (struct sockaddr_in *)&theirAddress;
int port = ntohs(soc->sin_port);
inet_ntop(AF_INET, &soc->sin_addr, nc.ipstr, sizeof ipstr);
nc.fd = new_fd;
nc.theirAddress = sockaddr_storage(theirAddress);
nc.sin_size = sin_size;
nc.port = port;
newConnections.push_back(nc);
}
This is called from here:
int main(int argc, const char* argv[])
{
RoutingManager *manager = new RoutingManager();
manager->ParseInputFile("topo.txt", 10, 3, " ");
manager->myConnection = new NetworkConnection("localhost", "7771");
manager->myConnection->SetSocketHints();
manager->myConnection->PopulateAddressInfo();
manager->myConnection->BindSocket();
while(1)
{
manager->myConnection->ListenForConnections(); // <- here
if (manager->myConnection->newConnections.size() > 0)
{
manager->ActivateNewNode();
}
}
}
And during the call to ActivateNewNode() I do:
bool
RoutingManager::ActivateNewNode()
{
TopologyIter iter = topology.begin();
do
{
if(!iter->second.online)
{
iter->second.online = true;
iter->second.connection = myConnection->newConnections.back();
myConnection->newConnections.pop_back();
cout << "Connected Activated!\n";
cout << "Node ID: " << iter->second.id << endl;
return true; //all good
}
iter++;
}while (iter != topology.end());
return false; //received a connection, but no more nodes to hand out
}
Where connection is the struct:
struct NodeConnection
{
int fd;
socklen_t sin_size;
struct sockaddr_storage theirAddress;
char ipstr[INET6_ADDRSTRLEN];
int port;
};
This works fine if I comment out the assignment of the connection during the call to ActivateNewNode(). I.e., this line:
iter->second.connection = myConnection->newConnections.back();
However, with it uncommented, then when I loop back through to continue listening for new connections, this snippet fails:
if (listen(socketFd, 15) == -1) {
perror("listen");
exit(1);
}
With the error: bad file descriptor
Can anyone tell me what I'm missing here?
put the listen() out of the while loop.
I followed this nice tutorial to create a simple non-blocking server using select() function. Here's what I have:
void setNonBlocking(int socketFD) {
int x;
x = fcntl(socketFD,F_GETFL,0);
fcntl(socketFD,F_SETFL,x | O_NONBLOCK);
return;
}
int initialize(char * port) {
int yes = 1;
listener = socket(PF_INET,SOCK_STREAM, 0);
if (listener < 0) {
perror("listener");
exit(EXIT_FAILURE);
}
if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
setNonBlocking(listener);
struct sockaddr_in server_address;
memset((char *) &server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
// server_address.sin_addr.s_addr = htonl(INADDR_ANY);
inet_aton("132.65.151.39",&(server_address.sin_addr));
server_address.sin_port = htons(atoi(port));
if (bind(listener, (struct sockaddr *) &server_address,
sizeof(server_address)) < 0 ) {
perror("bind");
close(listener);
exit(EXIT_FAILURE);
}
listen(listener,BACKLOG);
maxSocket = listener;
memset((char *) &clientQueue, 0, sizeof(clientQueue));
return 0;
}
void readSockets() {
int i;
cout << "in readSockets()" << endl;
if (FD_ISSET(listener,&sockets))
createConnection();
for (i = 0; i < 5; i++) {
if (FD_ISSET(clientQueue[i],&sockets))
readData(i);
} /* for (all entries in queue) */
}
int main(int argc, char* argv[]) {
if (argc != 2) {
fprintf(stderr,"usage: server port\n");
exit(EXIT_FAILURE);
}
if (initialize(argv[1]) != 0) {
exit(EXIT_FAILURE);
}
struct timeval timeout;
int value;
printf("server: waiting for connections...\n");
while(1) { // main accept() loop
build_select_list();
timeout.tv_sec = 1;
timeout.tv_usec = 0;
value = select(maxSocket, &sockets, (fd_set *) 0,(fd_set *) 0, &timeout);
if (value == -1) {
perror("select");
exit(EXIT_FAILURE);
}
if (value == 0) {
printf("%d",value);
fflush(stdout);
} else{
cout << "Value is " << value << endl;
readSockets();
}
}
return EXIT_SUCCESS;
}
My problem is simple - select always returns 0, meaning it does not get or does not respond to a new connection. I checked my client a day ago with a blocking more simple server and it did work, so I don't think its the porblem.
You'll notice that I tried both IP addresses:
server_address.sin_family = AF_INET;
// server_address.sin_addr.s_addr = htonl(INADDR_ANY);
Can anyone please help me? I feel lost :)
Please refer to man select, first parameter should be number of highest descriptor + 1, so in your case:
value = select(maxSocket + 1, &sockets, (fd_set *) 0,(fd_set *) 0, &timeout);