C 套接字编程-函数:错误的文件描述符
我在尝试创建以下代码的函数时遇到了一个问题,因此我可以重用它来轻松创建新套接字:C 套接字编程-函数:错误的文件描述符,c,linux,sockets,udp,C,Linux,Sockets,Udp,我在尝试创建以下代码的函数时遇到了一个问题,因此我可以重用它来轻松创建新套接字: 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.si
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");
}
我试着用以下方式来称呼它:
//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;
}
//发送消息
如果((发送到(套接字fd,cmd final,BUFFLEN,0,(结构sockaddr*)和服务地址,服务len))<0)
{
perror(“错误>发送命令失败:”);
返回0;
}
我很确定我搞乱了指针的一些基本知识(我是个初学者,有好几年没有用C编写代码了)。。。我尝试了很多不同的方法,但找不到任何解决办法。我会很感激一些帮助,或者到哪里去找
多谢各位 你调用open\u socket的方式与你想象的方式不一样。您正在作为参数传入
socket\u 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
}
函数
open_socket()
按值获取s_fd
。也就是说,当调用函数时,如中所示:
open_socket(socket_fd, serv_addr, tv, SERVER, PORT);
上面的函数调用获取作为函数参数s\u fd
的参数传递的socket\u fd
的副本。在函数内部,此副本是由socket()
获得的文件描述符写入的,而不是函数调用时的变量socket\u fd
C编程语言为您提供了两种机制来获取在open\u socket()中创建的文件描述符。
:
- 通过引用传递参数:调用方必须提供指向将存储文件描述符的变量的指针:
void open_socket(int *s_fd, /* ... */);
- 返回文件描述符作为函数调用的返回值:
int open_socket(/* ... */);
socket()
提供的接口更相似。当发生错误时,您可以简单地返回-1
以发出错误信号,因为每个文件描述符都是非负的(即:>=0)
由于您正在open_socket()
中设置结构sockaddr\u
中,因此也不需要通过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
}
int-open\u套接字(结构timeval-tv、const-char*ID\u-IP、int-ID\u-Port)
{
int s_fd;
s_addr中的结构sockaddr_;
如果((s_fd=套接字(AF_INET,SOCK_DGRAM,0))<0){
printf(“错误打开插座”);
后悔莫及;
}
s_addr.sin_family=AF_INET;/*定义使用的域*/
s_addr.sin_port=htons(ID_port);/*声明要使用的端口*/
s_addr.sin_addr.s_addr=inet_addr(“INADDR_ANY”)/*通过声明INADDR_ANY允许任何传入IP地址*/
if(setsockopt(s_fd,SOL_SOCKET,SO_RCVTIMEO,(const char*)和tv,sizeof(struct timeval))/*配置du timeout*/
转到错误关闭插座;
//将IPv4和IPv6地址从文本格式转换为二进制格式
if(inet\u pton(AF\u inet、ID\u IP和s\u addr.sin\u addr)!=1){
printf(“\n无效地址/不支持地址\n”);
转到错误关闭插座;
}
if(connect(s_fd,(struct sockaddr*)&s_addr,sizeof(s_addr))<0){
printf(“\n连接失败\n”);
转到错误关闭插座;
}
printf(“套接字连接\n”);
return s_fd;//返回套接字
错误关闭插座:
关闭(s_fd);
错误:
返回-1;//错误
}
如果在创建套接字之后(即:成功调用
socket()
)发生错误,则在从函数open\u socket()
返回之前,必须先关闭套接字(),否则将发生资源泄漏。这是使用goto
语句的少数几种情况之一:跳转到常用代码进行错误处理。我理解我在socket\u fd
中的错误,非常清楚,谢谢!但是,因为我想创建多个套接字,所以我有://SOCK 1 struct sockaddr\u in serv\u addr;int serv_len=sizeof(serv_addr)//服务地址2中的sock2结构sockaddr\u;int serv_len2=sizeof(serv_addr_2)
所以我想我需要把s\u addr
作为参数传递,对吗?因为我在更正函数时仍然存在“协议不支持的地址族”错误。。我没有提到,但是char*ID\u IP
和intID\u Port
是常量。替换为“define SERVER”192.168.0.10“&\define PORT 3000
@HacHac您不需要传递s\u addr
,因为您已经通过参数SERVER
和PORT
传递到open\u socket()
的参数ID\u-IP
和ID\u-PORT>对其内容进行了参数化,分别地它在我的系统上工作。如何调用更正后的函数?我这样调用函数socket\u fd\u 2=open\u socket(tv、IP\u 2、PORT\u 2)代码>此调用工作正常,但当我发送到(socket\u fd\u 2,cmd\u final,BUFFLEN,0,(struct sockaddr*)&serv\u addr\u 2,serv\u len\u 2)
时,我收到了一个关于错误协议地址的错误。尝试很多不同的事情,争论。。。。无法理解…@HacHac如果您打算使用sendto()
而不是send()
,为什么您实际上“connect()
ing”UDP套接字?您是对的,send()
正在工作。。。但是我有一种印象,那就是为了达到我的目标而努力,虽然我认为这相对简单,但也许我把这些概念混在了一起。因为如果用replacebind
而不是connect
,我得到了一个绑定错误。我有一台计算机,必须发送(首先)和接收(发送订单后)UDP中5个设备的数据(具有自己的IP、端口和大量订单…)。如果我愿意,也许你可以给我一个简单的代码示例(只是原型或大纲)
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
}