Reputation: 157
I have the following main function:
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char **argv) {
char *serv_IP;
in_port_t serv_port;
int sock;
struct sockaddr_in serv_addr;
serv_IP = argv[1];
serv_port = atoi(argv[2]);
if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
fprintf(stderr, "Failed to create TCP socket\r\n");
exit(1);
}
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
if (inet_pton(AF_INET, serv_IP, &serv_addr.sin_addr.s_addr) == 0) {
fprintf(stderr, "Invalid IP address\r\n");
exit(1);
}
serv_addr.sin_port = htons(serv_port);
if (connect(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
fprintf(stderr, "Failed to connect to serv\r\n");
exit(1);
}
else {
printf("You're connected!\n);
}
close(sock)
return 0;
}
Now, this code works just fine. However, what I want to do is to replace the call to connect()
with a helper function call to something like this:
void function(int sock, struct sockaddr_in *serv_addr) {
if (connect(sock, (struct sockaddr *) serv_addr, sizeof(serv_addr)) < 0) {
printf("Server IP = %s\n", inet_ntoa(serv_addr->sin_addr));
printf("Server port = %d\n", ntohs(serv_addr->sin_port));
fprintf(stderr, "Failed to connect to server\r\n");
exit(1);
}
else {
// Do other stuff
}
}
I remove the call to connect()
from main()
, and replace it with the function call:
function(sock, &serv_addr);
As soon as the function is called, the correct IP and port numbers are printed out, but I still fail to connect to my server.
The only difference is, in my main function()
, I preface serv_addr
in the connect call with the &
— i.e., connect(sock, (struct sockaddr *)
, &serv_addr
, sizeof(serv_addr)
— to reference its address, and I don't do that in the helper function because the address of serv_addr
is already being passed as an argument — i.e., connect(sock, (struct sockaddr *)
, serv_addr
, sizeof(serv_addr)
. It makes no difference if I add the &
, just in case you were wondering.
So, with the &serv_addr
being passed to function()
seemingly correctly, as verified by me being able to print out the correct IP and port numbers, why is it that I can connect in main()
, but not when I pass the serv_addr
struct as an argument to another function and call connect()
from there?
Upvotes: 1
Views: 7943
Reputation: 157
I never would have thought about the return of sizeof()
as a potential problem with returning different sizes for actual values vs. pointers to values.
The exact line that fixed it was:
if (connect(sock, (struct sockaddr *) serv_addr, sizeof(struct sockaddr_in)) < 0)
I was right about not needing the '&' in front of serv_add. You also need the "struct" in sizeof()
or else it returns sockaddr_in
as an undeclared variable.
Upvotes: 0
Reputation: 595981
sizeof(serv_addr)
returns 16 when serv_addr
is declared as sockaddr_in
, but returns 4 (in 32bit) or 8 (in 64bit) when declared as sockaddr_in*
. It is too small either way, AF_INET
needs 16. Had you looked at errno
when connect()
failed, it would have told you that you were passing an invalid parameter value.
You need to use sizeof(sockaddr_in)
, either directly:
void function(int sock, struct sockaddr_in *serv_addr)
{
if (connect(sock, (struct sockaddr *) serv_addr, sizeof(struct sockaddr_in)) < 0)
Or indirectly via sizeof(*serv_addr)
:
void function(int sock, struct sockaddr_in *serv_addr)
{
if (connect(sock, (struct sockaddr *) serv_addr, sizeof(*serv_addr)) < 0)
Upvotes: 2