【问题标题】:socket code only works on a 16 byte buffer套接字代码仅适用于 16 字节缓冲区
【发布时间】:2021-11-02 13:38:40
【问题描述】:

我很难更改我的服务器发送的数据量并让它发送数据。此代码失败,但当我将 buffer 的大小更改为 16 个字符时有效。

这是来自 transferclient.c 的代码

#include <errno.h>
#include <getopt.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>

#define BUFSIZE 218

int main(int argc, char **argv) {
  unsigned short portno = 10823;

    int sock = 0;
    struct sockaddr_in serv_addr;
    char buffer[32] = {0};
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("\n Socket creation error \n");
        return -1;
    }

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(portno);
    printf("Attemping to connect\n");
    if (connect(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
    {
        printf("\nConnection Failed \n");
        return -1;
    }
    printf("Connected\n");
    read(sock, buffer, 16);
    return 0;
}

这是来自 transferserver.c 的代码

#include <errno.h>
#include <getopt.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>

#define BUFSIZE 218

int main(int argc, char **argv) {
  int portno = 10823;          /* port to listen on */

    int server_fd, new_socket;
    struct sockaddr_in address;
    int opt =1;
    int addrlen = sizeof(address);

    // Creating socket file descriptor
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
    {
        perror("socket failed");
      exit(EXIT_FAILURE);
    }

    // Attaching the socket to the port
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)))
    {
        perror("setsockopt");
        exit(EXIT_FAILURE);
    }
    
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(portno);
   
   
    // Forcefully attaching socket to the port
    if (bind(server_fd, (struct sockaddr *) &address, sizeof(address))<0)
    {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }
    if (listen(server_fd, 3) < 0) {
        perror("listen");
        exit(EXIT_FAILURE);
    }
    printf("Listening\n");
    
    while ((new_socket = accept(server_fd, (struct sockaddr *) &address, (socklen_t*) &addrlen)) > 0)
    {
        printf("%d\n", new_socket);
        printf("Socket connected\n");
    }
    return 0;
}

服务器端

聆听

4

套接字连接


***Client Side***
``` 
Attemping to connect

Connected

当我将 transferclient.c 中的行更改为 32 字节时。

char buffer[32] = {0};

套接字连接失败。

服务器端

Listening

客户端

Attemping to connect

这是为什么呢?

【问题讨论】:

  • 我怀疑问题出在您没有向我们展示的代码中。请提供minimal reproducible example
  • 根据您在问题中发布的输出,"Connected""\nConnection Failed \n" 都不会被打印出来。你确定这是正确的吗?如果是这样,您的程序会崩溃吗?
  • 是的,这是正确的。似乎套接字开始连接并挂起。
  • 我建议你把printf("Connected");改成printf("Connected\n");(加换行符)。或者您应该在该语句之后添加fflush( stdout );。如果您不确定消息是否从输出缓冲区中刷新,那么您可能永远看不到它,例如,如果程序随后进入无限循环。有关更多信息,请参阅this question。另一种方法是使用stderr 而不是stdout 来获取诊断消息,因为该流通常是无缓冲的。
  • 如果您需要调试帮助,minimal reproducible example 是强制性的。

标签: c sockets


【解决方案1】:

在客户端代码中,您似乎没有设置serv_addr 的所有字段。

struct sockaddr_in serv_addr;

[...]

serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(portno);

因为你没有设置serv_addr.sin_addr,所以当你将它传递给函数connect时,它会有一个不确定的(垃圾)值。

我的猜测是更改数组的大小导致serv_addrsin_addr 字段具有不同的初始(垃圾)值。这就是为什么代码在buffer 的大小为16 时有效,但在其大小为32 时失败的原因。

【讨论】:

    【解决方案2】:

    在我看来...除了其他答案中已经提到的内容之外,您缺少常量...您应该定义如下内容:

    #define BUFFER_SIZE    (32)
    

    然后使用

        char buffer[BUFFER_SIZE];
    

        read(sock, buffer, BUFFER_SIZE);
    

    或者,如果您不喜欢这种方法,请使用其他方法:

        char buffer[32];
    

    以后

        read(sock, buffer, sizeof buffer);
    

    但是,如果您在缓冲区大小和 read() 调用中输入不同的数字,则当您使用 16 作为要读取的字符数调用 read() 时,它不起作用是正常的。

    顺便说一句,您要求套接字读取固定数量的字节是很常见的,并且它返回的字节数少于您请求的数量,因此检查@的返回值非常重要987654329@。比如:

        ssize_t n = read(sock, buffer, BUFFER_SIZE);
    

    buffer[n]buffer[sizeof buffer - 1] 对您的代码没有任何用处(之前阅读的其余部分或类似内容)通常使用以下内容打印它:

        if (n > 0)
            printf("Read: [%.*s]\n", n, buffer);
    

    这将打印接收到的有效字符的数量,而不是缓冲区中它们后面的内容。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-22
      • 1970-01-01
      • 2012-09-25
      • 1970-01-01
      相关资源
      最近更新 更多