【问题标题】:Trouble while reading from socket从套接字读取时出现问题
【发布时间】:2015-07-17 06:41:29
【问题描述】:

我正在尝试从套接字读取字符;这是我为此创建的函数,很大程度上受Here 启发,我在这里删除了一些不相关的部分(此示例正在正确编译)。

int process(int socketfd, void *buffer, int n)
{
  int totread = 0;
  char ch;
  int numread;

  for(;;)
  {
    numread = read(socketfd, &ch, 1);

    if(numread == 0) {
        if (totread == 0) {
            return 0;
        } else {
            break;
        }
    } else {
        if(totread < n-1) {
            totread++;
            printf("totread: %d\n", totread);
            printf("Here is OK, ch value gets printed %c\n", ch);
            *buffer++ = ch;
            printf("With help provided, this line gets printed\n");
            printf("But the value <%s> of buffer, is blank (<> output)\n, buffer);
        }
        if (ch == '\n') {
            printf("%c\n", ch);
            printf("%s\n", buffer);
            break;
        }
    }
}
return totread;
}

我不明白为什么第二行没有打印出来。 很明显,*buf++ = ch 指令有问题;但它看起来是正确的。它只是将字符读取到字符数组 buf 的下一个值。我在编译时看不到错误或警告,客户端在第一行打印后断开连接,第二行未到达。

编辑

这是我初始化缓冲区的方法:

char *buffer = "";
int l = process(newsockfd, buffer, 100);
printf("Number read (function network) %d\n", l);

这可能不是合适的方法;我还尝试指定一个固定长度,例如char buffer = [255]; 该函数不会退出,但没有打印任何内容。我是C编程的新手,非常感谢您的帮助!

【问题讨论】:

  • 当你说第二行没有被打印出来时,我想你的意思是因为程序崩溃了。这很可能是在bufNULL 或无效内存时写入buf 引起的segv。当您在 gdb 下运行它并使用 -g 编译以包含调试符号时会发生什么?
  • 缓冲区够大吗?另外,我相信 buf[0] 永远不会被写入,这似乎是一个等待发生的潜在问题。
  • 请告诉我们如何调用这个函数,特别是传入的缓冲区是如何定义和初始化的。
  • 另外:您是否有意遗漏了用于错误检查的代码以使该示例更好地可读?
  • n(传入的)是干什么用的?

标签: c linux sockets io


【解决方案1】:
int process(..., void * b, ...
{
  ...

  *b++ = ...

取消引用和/或增加void-pointer 是无效的 C。编译器至少应该对此发出警告。

重新编译您的代码并打开所有警告(对于 gcc,请为此传递选项 -Wall -Wextra -pedantic)。然后修复代码,直到不再发出警告。


参考您对如何调用相关函数的编辑:

这个

char *buffer = "";

不声明缓冲区,而只是一个指针。该指针指向大小为1 的字符串文字。根据定义,字符串字面量是一个常量。

总结一下:您向您的process()-函数提供一个指向大小为1 的常量内存的指针。

这个问题:

  1. 您无法读取常量内存。
  2. 即使 1. 不适用,您也只能读取 1 字节。

要解决此问题,请按如下方式更改代码:

char buffer[100] = ""; /* Define a buffer of 100 characters size and 
                          initialise it to all `0`s. */
int l = process(newsockfd, buffer, 100);

根据process() 阻塞,您需要查看read() 函数:如果它被调用但发件人没有发送任何内容,只要连接还在,它就不会返回。

并且:让process() 处理作为n 传入的值。

【讨论】:

  • 我使用eclipse作为IDE;也许这不是 C 编程的最佳选择:/
  • @philippe:Eclipse 可以很好地用于 C 编程,至少如果你正确的话.. ;-) 如果使用 CDT,那么无论如何你都在使用 gcc。 Eclipse 不是编译器/链接器,而只是 IDE。
  • 我在Eclipse中添加了-Wall -Wextra -Werror -pedantic -pedantic-errors;我纠正了所有错误,代码现在编译。感谢您对编译选项的建议!
  • 尚未处理作为n 传入的值,但考虑到您的答案编辑了我的代码。现在,程序没有崩溃,因为它至少到达了下一个printf;但buffervalue 不会受到影响。
  • 好的,我现在把传入的值作为n处理;此外,我处理换行符;这时候,我肯定知道buffer被实例化了;输入\n 时会打印出来
【解决方案2】:

尝试将第一行更改为 char *buf = (char *) 缓冲区; 并在

上使用带有 -Werror 的 gcc 进行编译

【讨论】:

  • 这不会发生任何事情:/
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-02
  • 1970-01-01
  • 2015-09-27
  • 2010-12-10
  • 2012-10-04
相关资源
最近更新 更多