我在尝试创建以下代码的函数时遇到问题,因此我可以重复使用它来轻松创建新套接字:
if ( (socket_fd = socket(AF_INET, SOCK_DGRAM, 0) ) < 0 ) /* return 1 if okay */
{
printf("ERROR opening socket ... 1");
}
serv_addr.sin_family = AF_INET; /*Define the domain used*/
serv_addr.sin_port = htons(PORT); /*Declare port #PORT to be used*/
serv_addr.sin_addr.s_addr = inet_addr("INADDR_ANY"); /*Permit any incoming IP address by declaring INADDR_ANY*/
setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv , sizeof (struct timeval));
// Convert IPv4 and IPv6 addresses from text to binary form
if(inet_pton(AF_INET, SERVER, &serv_addr.sin_addr)<=0)
{
printf("\nInvalid address/ Address not supported \n");
return -1;
}
if (connect(socket_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("\nConnection Failed \n");
return -1;
}
else
{
printf("\n Connected \n");
}
上面的代码对我很有用,但是当我尝试创建一个简单的函数来重新组合时,当我尝试使用sendto()
发送cmd时,我有错误bad file descriptor
。
所以这是我的功能:
void open_socket( int s_fd, struct sockaddr_in s_addr, struct timeval tv, char* ID_IP, int ID_Port)
{
if ( (s_fd = socket(AF_INET, SOCK_DGRAM, 0) ) < 0 ) /* return 1 if okay */
{
printf("ERROR opening socket ");
}
s_addr.sin_family = AF_INET; /*Define the domain used*/
s_addr.sin_port = htons(ID_Port); /*Declare port #PORT to be used*/
s_addr.sin_addr.s_addr = inet_addr("INADDR_ANY"); /*Permit any incoming IP address by declaring INADDR_ANY*/
setsockopt(s_fd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv , sizeof (struct timeval)); /*config du timeout*/
// Convert IPv4 and IPv6 addresses from text to binary form
if(inet_pton(AF_INET, ID_IP, &s_addr.sin_addr)<=0)
{
printf("\nInvalid address/ Address not supported \n");
}
if (connect(s_fd, (struct sockaddr *)&s_addr, sizeof(s_addr)) < 0)
{
printf("\nConnection Failed \n");
}
else
{
printf("Socket Connected\n" );
}
}
我尝试用:
来调用它 //SOCKET 1
struct sockaddr_in serv_addr; /* Server Socket address structure*/
int serv_len=sizeof(serv_addr);
int socket_fd;
struct timeval tv;
tv.tv_sec=1 ;
tv.tv_usec=0;
//FUNCTION CALL
open_socket( socket_fd, serv_addr, tv, SERVER, PORT);
,错误出现在这里:
//send the message
if ( (sendto(socket_fd , cmd_final, BUFFLEN , 0 , (struct sockaddr *)&serv_addr, serv_len) ) < 0 )
{
perror("ERROR > send cmd failed : ");
return 0;
}
我很确定我正在弄乱一些关于指针的基本信息(我是初学者,而且几年没有用C语言编码)...我尝试了很多不同的东西,却找不到任何解决方案。我希望得到一些帮助或在哪里寻找!
非常感谢!
答案 0 :(得分:2)
您拨打open_socket
的方式并不像您想象的那样工作。您作为参数传递socket_fd
,因此该功能无法更新。你真的应该将新创建的套接字作为返回值返回 - 这样你就可以通过返回-1来处理错误,你的调用代码可以检查并执行相应的操作。
int open_socket( struct sockaddr_in s_addr, struct timeval tv, char* ID_IP, int ID_Port)
{
int s_fd;
// Code goes here, returning -1 if it fails at any point
return s_fd;
}
并像这样称呼它
socket_fd = open_socket(serv_addr, tv, SERVER, PORT);
if(socket_fd==-1)
{
// Handle failure to create socket
}
答案 1 :(得分:0)
函数open_socket()
按值<{1}} 取值。也就是说,当函数被调用时:
s_fd
上面的函数调用获得了作为函数参数open_socket(socket_fd, serv_addr, tv, SERVER, PORT);
的参数传递的socket_fd
的副本。在函数内部,此副本是使用s_fd
获取的文件描述符而不是函数调用中的变量socket()
编写的。
C编程语言为您提供了两种机制来获取在socket_fd
内创建的文件描述符:
通过引用传递参数 :调用者必须提供指向将存储文件描述符的变量的指针:
open_socket()
将文件描述符作为函数调用的返回值返回:
void open_socket(int *s_fd, /* ... */);
我建议您坚持使用后者,因为界面类似于系统调用int open_socket(/* ... */);
提供的界面。发生错误时,您只需返回socket()
即可发出错误信号,因为每个文件描述符都是非负数(即:&gt; = 0)。
由于您在-1
内部设置了结构open_socket()
,因此无需通过sockaddr_in
参数传递它。
s_addr
如果在创建套接字后发生错误(即:在成功调用int open_socket(struct timeval tv, const char* ID_IP, int ID_Port)
{
int s_fd;
struct sockaddr_in s_addr;
if ((s_fd = socket(AF_INET, SOCK_DGRAM, 0) ) < 0 ) {
printf("ERROR opening socket ");
goto err;
}
s_addr.sin_family = AF_INET; /*Define the domain used*/
s_addr.sin_port = htons(ID_Port); /*Declare port #PORT to be used*/
s_addr.sin_addr.s_addr = inet_addr("INADDR_ANY"); /*Permit any incoming IP address by declaring INADDR_ANY*/
if (setsockopt(s_fd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv , sizeof (struct timeval))) /*config du timeout*/
goto err_close_socket;
// Convert IPv4 and IPv6 addresses from text to binary form
if (inet_pton(AF_INET, ID_IP, &s_addr.sin_addr) != 1) {
printf("\nInvalid address/ Address not supported \n");
goto err_close_socket;
}
if (connect(s_fd, (struct sockaddr *)&s_addr, sizeof(s_addr)) < 0) {
printf("\nConnection Failed \n");
goto err_close_socket;
}
printf("Socket Connected\n" );
return s_fd; // return the socket
err_close_socket:
close(s_fd);
err:
return -1; // error
}
之后),套接字必须是 socket()
d 才能从函数返回{ {1}},否则会出现资源泄漏。这是使用close()
语句的少数情况之一:跳转到用于错误处理的公共代码。