I am trying to modify the wrk codebase so that it will connect to multiple servers instead of just the one. I have found and am modifying the connect_socket function to this end but am getting the following output when it runs:
143.204.186.52
connect: Invalid argument
64.190.62.111
connect: Invalid argument
45.33.18.44
connect: Invalid argument
64.190.62.111
connect: Invalid argument
52.128.23.153
connect: Invalid argument
173.255.194.134
connect: Invalid argument
^C Thread Stats Avg Stdev Max /- Stdev
Latency 0.00us 0.00us 0.00us -nan%
Req/Sec 0.00 0.00 0.00 -nan%
0 requests in 1.66s, 0.00B read
Socket errors: connect 100000, read 0, write 0, timeout 0
Requests/sec: 0.00
Transfer/sec: 0.00B
Here is the modified function that I am calling:
static int connect_socket(thread *thread, connection *c) {
struct addrinfo *addr = thread->addr;
struct aeEventLoop *loop = thread->loop;
int fd, flags;
char ip[128];
struct sockaddr_in myaddr;
if (fscanf(fp, "8s", ip) == 1) {
printf("%s\n", ip);
}
memset(&myaddr, '0', sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_port = htons(80);
if(inet_pton(AF_INET, ip, &myaddr.sin_addr)<=0)
{
printf("\n inet_pton error occured\n");
}
fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
if (connect(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) == -1) {
if (errno != EINPROGRESS) goto error;
}
flags = 1;
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &flags, sizeof(flags));
flags = AE_READABLE | AE_WRITABLE;
if (aeCreateFileEvent(loop, fd, flags, socket_connected, c) == AE_OK) {
c->parser.data = c;
c->fd = fd;
return fd;
}
error:
perror("connect");
thread->errors.connect ;
close(fd);
return -1;
}
I guess it must be a problem with my arguments to connect. Any ideas what I am doing wrong?
CodePudding user response:
There is a mistake in the following line:
fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
It should be:
fd = socket(AF_INET, addr->ai_socktype, addr->ai_protocol);
CodePudding user response:
This code is a logic mess.
The use of the addrinfo struct implies the getaddrinfo() function is being used elsewhere before the thread is started.
Your thread is being passed in an addrinfo, and is then creating the socket based on the IP address type specified by that addrinfo, but is ignoring the actual IP address stored in the addrinfo (which could be either an IPv4 or IPv6 address). It is instead obtaining an IP address as a string from elsewhere, parsing it only as an IPv4 address, and then passing it to connect() in a sockaddr_in struct. connect() can fail with an "invalid argument" error in that case if the socket is not an IPv4 (AF_INET) socket, ie if it is an IPv6 (AF_INET6) socket instead, which requires a sockaddr_in6 struct.
To fix this, you need to either:
get rid of the
sockaddr_inand use the IP address in thesockaddras-is:connect(fd, addr->ai_addr, addr->ai_addrlen)get rid of the
sockaddrand hard-code the socket type asAF_INETto match the use ofsockaddr_in:socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
