【发布时间】:2015-06-04 01:30:57
【问题描述】:
我正在尝试从 C 中的套接字读取数据。将会有两条消息。
我正在尝试将消息的大小发送到套接字,以便 read() 命令知道消息何时结束并可以在该点停止读取。否则,它会将两条消息读入一个 blob。问题是 read 命令将缓冲区设置为 0,即使它读取 > 0 个字节。
代码如下:
n = read(newsockfd, buffer, sizeof(int));
int bytes_to_read = atoi(buffer);
fprintf(stdout, "Here is the size of the data to look for: %d", bytes_to_read);
/*read message*/
fprintf(stdout, "Reading first message.\n");
int bytesread = 0;
int chunk = bytes_to_read > 255 ? 255 : bytes_to_read;
do {
bzero(buffer,256);
n = read(newsockfd,buffer,chunk);
bytes_read += n;
fprintf(stdout, "The value of n is %d and here is the new buffer after the first read: %s and new buffer length is : %d\n", n, buffer, strlen(buffer));
strcat(plaintext, buffer);
size += 256;
plaintext = realloc(plaintext, size);
} while (bytes_read < bytes_to_read);
我得到的输出显示 n = 36(如预期)但缓冲区为 0,缓冲区的长度为 1。
为什么 read() 命令会将缓冲区设置为 0?有没有更简单的方法来告诉 read() 在哪里停止阅读?
编辑: 根据我得到的反馈,我彻底重写了这个。请注意,我知道客户端将发送一个数据包,其中包含数据中的字节数作为 unit32_t,然后它将发送数据。
char * readText(int newsockfd) {
char * text = malloc(256);
char buffer[256];
int n;
int size = 256;
/*find out how many bytes are in the data*/
uint32_t bytes_to_read;
n = read(newsockfd, &bytes_to_read, sizeof(uint32_t));
bytes_to_read = ntohl(bytes_to_read);
/*read data from client*/
int bytes_read = 0;
int bytes_left = bytes_to_read;
/*the maximum we can read at one time is 255 bytes since that is the size of the buffer.
* the buffer could have been larger but we'd still have to check the data size and keep calling
* read() until we get all of the data.
* If the data to read is smaller than the buffer, then we just read it in one go. If the data is larger,
* then we read it in 255 byte-sized chunks until we have read all of it*/
int chunk = (bytes_to_read > 255) ? 255 : bytes_to_read;
do {
bzero(buffer,256);
n = read(newsockfd,buffer,chunk);
/*copy over the data we have read so far into the text buffer
We offset by the amount we have already read in so we do not overwrite the data already
in the array*/
memcpy(text + bytes_read, buffer, n);
bytes_read += n;
bytes_left -= n;
/*if we have less than 255 bytes left, just read that amount. This prevents read() from pulling in too much data and messing up the next read() call*/
chunk = (bytes_left > 255) ? 255 : bytes_left;
size += n;
/*grow the text variable by as much as we just read in. This makes room for
the next chunk of data. The next chunk could be as large as 255 bytes*/
text = realloc(text, size);
} while (bytes_read < bytes_to_read);
text[bytes_read] = '\0'; //null terminate our string so we can use string functions on it.
if (n < 0) error("ERROR reading from socket");
return text; }`
【问题讨论】:
-
buffer是一个指向缓冲区的指针(或者可能是缓冲区本身,如果它被声明为一个数组),它的长度是你分配的字节数。这不会改变。 -
1) 从套接字读取时,应使用 'recv()' ,而不是 'read()' 2) read/recv 不会终止读取数据。所以代码必须专门这样做。 3) 在第一次调用 strcat() 之前,'plaintext[]' 的第一个字节必须是 '\0' 4) strlen(buffer) 可以是任何值,因为读取的字符串尚未终止,5) 使用 realloc 时() 在将返回值分配给目标指针之前总是检查(!=NULL),
-
继续:6) 第一次调用 read() 需要 4 个 ascii 字符(sizeof(int))。这可能正确也可能不正确。如果只传输 3 个字符,该函数将永远挂起,7) 发布的代码中还有其他几个问题
-
关于这一行:'int chunk = bytes_to_read > 255 ? 255:字节_to_read;'由于 C 运营商的领导,这条线可能会失败。建议:'int chunk = (bytes_to_read > 255) ? 255:bytes_to_read;'