I have a program listening on a socket defined below. The problem I am seeing is that on the first connection, the client address value is "0.0.0.0".
The client is not on the local machine, it is connecting from a remote IP. The connection seems fine, other than the incorrect IP.
All subsequent connections have the actual remote IP address of the connecting client, such as "8.8.8.8".
Why does the first connection report the address as "0.0.0.0"?
void client_loop(int client_socket, const string& client_address) {
LOG4CXX_INFO(logger, "client_loop(" << client_address << ")");
while(active) {
boost::this_thread::sleep(seconds(1));
}
}
void server_loop(unsigned short server_port) {
LOG4CXX_INFO(logger, "server_loop(" << server_port << ")");
int server_socket = socket(AF_INET, SOCK_STREAM, 0);
if (server_socket < 0) {
LOG4CXX_ERROR(logger, "socket() - " << strerror(errno));
return;
}
in_addr_t s_addr = htonl(INADDR_ANY);
struct sockaddr_in server_sockaddress;
struct sockaddr_in client_sockaddress;
unsigned int client_length(0);
memset((char *) &server_sockaddress, 0, sizeof(server_sockaddress));
memset((char *) &client_sockaddress, 0, sizeof(client_sockaddress));
server_sockaddress.sin_family = AF_INET;
server_sockaddress.sin_addr.s_addr = s_addr;
server_sockaddress.sin_port = htons(server_port);
bind(server_socket, (struct sockaddr*) &server_sockaddress, sizeof(server_sockaddress));
listen(server_socket, 10);
int client_socket(0);
LOG4CXX_INFO(logger, "Listening on Port " << port);
while(active) {
client_socket = accept(server_socket, (struct sockaddr *) &client_sockaddress, &client_length);
if(client_socket > 0) {
string client_address(inet_ntoa(client_sockaddress.sin_addr));
new boost::thread(boost::bind(client_loop, client_socket, client_address));
} else {
LOG4CXX_ERROR(logger, "accept() - " << strerror(errno));
}
memset((char *) &client_sockaddress, 0, sizeof(client_sockaddress));
}
}
Your problem is that you're not initializing client_length
into sizeof(client_sockaddr)
, but keep it as 0 for the 1st run.
From the accept
documentation:
The returned address is truncated if the buffer provided is too small; in this case, addrlen will return a value greater than was supplied to the call.
This means that on the 1st run, the system isn't filling any data into your sockaddr
struct, which was initialized to 0 - and thus the result you're getting of 0.0.0.0.
The next runs will use the size returned by the previous system call which fixes the issue on subsequent runs (at the risk of buffer overflow, mind you).