Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 套接字编程-函数:错误的文件描述符_C_Linux_Sockets_Udp - Fatal编程技术网

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
和int
ID\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()
正在工作。。。但是我有一种印象,那就是为了达到我的目标而努力,虽然我认为这相对简单,但也许我把这些概念混在了一起。因为如果用replace
bind
而不是
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
}