gpt4 book ai didi

C套接字编程: Invalid argument error on connect()

转载 作者:可可西里 更新时间:2023-11-01 02:35:05 27 4
gpt4 key购买 nike

我正在编写客户端作为 TCP 客户端服务器程序的一部分。

我的代码到达连接部分并抛出一个 Invalid argument 错误,我已经检查了几次代码,但我找不到问题。

代码接收 3 个参数,第一个是 IP 地址或主机名,第二个是端口,第三个是要发送的消息的最大长度。

我的代码使用 getaddrinfo 来转换 IP 地址或主机名、创建所需的变量、启动连接、读取文件、发送数据和接收数据。

我运行代码:

gcc -std=gnu99 -O3 -Wall -o pcc_client pcc_client.c
./pcc_client 127.0.0.1 2233 4

输出是:

sockaddr_in initialized
Error starting connection : Invalid argument

#include <stdlib.h>
#include <stdio.h>
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <dirent.h>

#define FILE_ADDR "/dev/urandom"

int main(int argc, char *argv[]) {
if (argc != 4) {
printf("should receive 3 arguments Received %d args\n", argc);
exit(1);
}

//Get command line arguments
unsigned int port = atoi(argv[2]);
int length = atoi(argv[3]); //Number of bytes to read
char* buffer = malloc(length * sizeof(char)); //Buffer to hold data read from file
char* recvBuf = malloc(10 * sizeof(char)); // Buffer to hold response from server

struct addrinfo hints, *servinfo, *p;
struct sockaddr_in *serv_addr;
int rv;
char ip[100];

memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;

if ((rv = getaddrinfo(argv[1], argv[2], &hints, &servinfo)) != 0) {
perror("getaddrinfo error\n");
return 1;
}
for (p = servinfo; p != NULL; p = p->ai_next) {
serv_addr = (struct sockaddr_in *) p->ai_addr;
strcpy(ip, inet_ntoa(serv_addr->sin_addr));
}
// inet_aton(ip, &h.sin_addr);
freeaddrinfo(servinfo);

//Initialize socket
int sockfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) //Error creating socket
{
perror("Error creating socket \n");
exit(1);
}

printf("socket created\n");

//Initialize sockaddr_in structure
memset((void*)serv_addr, 0,(size_t) sizeof(*serv_addr));
serv_addr->sin_family = AF_INET;
serv_addr->sin_port = htons(port);
serv_addr->sin_addr.s_addr = inet_addr("127.0.0.1"); //change?


//Initialize connection
if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { //Error connecting
perror("Error starting connection \n");
exit(1);
}
printf("connect succesful\n");

exit(0);

}

最佳答案

您使用的 serv_addr 完全错误。

您已将 serv_addr 声明为 sockaddr_in* 指针。 getaddrinfo() 成功退出后,您将循环输出列表,分配 serv_addr 指向列表中的每个 ai_addr,然后您释放列表,使 serv_addr 指向无效内存。然后,当您尝试用数据填充 serv_addr 时,您会浪费内存。然后你最终甚至根本没有将指向 sockaddr_in 的有效指针传递给 connect(),你实际上传递了一个指向 sockaddr_in 的指针,这就是它提示“无效参数”的原因。

事实上,您对这种情况的处理通常都是错误的。使用 getaddrinfo() 时,由于它返回可能包含多个套接字地址的链表,因此您需要遍历该列表以尝试 connect() 到每个地址,直到其中一个他们是成功的。如果您想要升级代码以同时支持 IPv4 和 IPv6(通过设置 hints.ai_family = AF_UNSPEC;),这一点尤其重要。

尝试更像这样的东西:

int main(int argc, char *argv[])
{
if (argc != 4)
{
printf("should receive 3 arguments Received %d args\n", argc);
exit(1);
}

struct addrinfo hints, *servinfo, *p;
int sockfd = -1;

memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET; // or AF_UNSPEC
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;

int rv = getaddrinfo(argv[1], argv[2], &hints, &servinfo);
if (rv != 0)
{
perror("getaddrinfo error\n");
return 1;
}

for (p = servinfo; p != NULL; p = p->ai_next) {
//Initialize socket
sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if (sockfd < 0) continue;
//Initialize connection
rv = connect(sockfd, p->ai_addr, (socklen_t) p->ai_addrlen);
if (rv == 0) break;
close(sockfd);
sockfd = -1;
}

freeaddrinfo(servinfo);

if (sockfd < 0) //Error creating/connecting socket
{
perror("Error creating/connecting socket \n");
exit(1);
}

printf("connect successful\n");

...

close(sockfd);
exit(0);
}

关于C套接字编程: Invalid argument error on connect(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48348858/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com