【问题标题】:UDP Sockets in C - Sendto() Send failed : invalid argumentsC 中的 UDP 套接字 - Sendto() 发送失败:参数无效
【发布时间】:2016-01-07 21:59:00
【问题描述】:

我正在尝试以非常简单/基本的方式在 C 中实现 UDP 套接字。我的程序旨在在终端之间发送/接收文件,每个终端上运行一个程序。我的客户端代码中的 sendto() 函数有问题。这是我的代码:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include <errno.h>

#define BUFFER_SIZE 512

int main(int argc, char *argv[])
{
    struct sockaddr_in client;
    int sockfd, bytes, errno, slen = sizeof(client);
    char buffer[BUFFER_SIZE];

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    if(sockfd == -1)
    {
        perror("Socket creation failed.");
        return 0;
    }

    client.sin_addr.s_addr = INADDR_ANY;
    client.sin_family = AF_INET;
    client.sin_port = htons( 0 );

    if( bind(sockfd, (struct sockaddr *)&client, sizeof(client)) == -1)
    {
        perror("Bind call failed.");
        return 0;
    }

    while(1)
    {
        printf("Enter message : ");
        fgets(buffer, BUFFER_SIZE, stdin);

        printf("Message: %s\n", buffer);
        bytes = sendto(sockfd, buffer, strlen(buffer), 0, (struct sockaddr *)&client, sizeof(client));

        printf("Bytes: %d\n", bytes);

        if(bytes == -1)
        {
            printf("Error number: %d", errno);
            perror("Send failed.");
            return 0;
        }

        memset(buffer,'\0', BUFFER_SIZE);

        if( recvfrom(sockfd, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&client, &slen) == -1)
        {
            perror("Recieve failed.");
            return 0;
        }

        puts(buffer);
    }

    close(sockfd);

    return 0;   
}

无论我在缓冲区中输入什么,我总是会从 sendto() 中得到错误号 22 的无效参数。我已经尝试了所有遇到的解决方案或调整,但似乎没有任何效果。

【问题讨论】:

  • 您正在尝试发送到端口 0。这是无效的。
  • 您可以绑定到端口 0,这会导致自动选择端口。但是您不能发送到端口 0。您可以在绑定后使用getsockname 找出选择了哪个端口。
  • 当您调用bind() 时,您正在设置本地端口。端口 0 意味着操作系统应该找到一个未使用的端口并绑定它。
  • 无关:在调用printf()之后再调用perror()是没有意义的,因为printf()可以改变errno
  • 您需要两种不同的sockaddr_in 结构,一种用于绑定客户端地址/端口,另一种用于指定目标地址/端口。

标签: c sockets udp sendto


【解决方案1】:

只要在bind()后面加上这段代码

getsockname(sockfd, (struct sockaddr *)&client, &slen);

手册页

 DESCRIPTION
     The getsockname() function returns the current address for the specified
     socket.

     The address_len parameter should be initialized to indicate the amount of
     space pointed to by address.  On return it contains the actual size of
     the address returned (in bytes).

     The address is truncated if the buffer provided is too small.

RETURN VALUES
     The getsockname() function returns the value 0 if successful; otherwise
     the value -1 is returned and the global variable errno is set to indicate
     the error.

【讨论】:

  • @EJP 从外观上看,他想将数据包发送回他正在侦听的同一端口。如果是这样的话,这将解决它。他说这是“无效参数”而不是分段错误。
猜你喜欢
  • 1970-01-01
  • 2018-06-16
  • 2011-04-25
  • 2014-01-04
  • 1970-01-01
  • 2015-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多