我在 C 中有以下套接字代码。我试图在每个周期接收 70 字节的数据。但是,我只得到 4 个字节的数据。完整的数据是这样的(十六进制):
4D43475000856308000004B2DE1F04009E00200100000000696CF7AB002F1A00000000
000000325C000402069BFDE70857E22502F41C000036000000DF0B0932100B09DC0719
问题是什么?我试图研究许多 StackOverflow 答案,但没有任何帮助。
代码如下:
void doprocessing (int sock);
int main( int argc, char *argv[] ) {
int sockfd, newsockfd, portno, clilen;
char buffer[1024];
struct sockaddr_in serv_addr, cli_addr;
int n, pid;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}
/* Initialize socket structure */
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = 14064;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
/* Now bind the host address using bind() call.*/
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR on binding");
exit(1);
}
/* Now start listening for the clients, here
* process will go in sleep mode and will wait
* for the incoming connection
*/
listen(sockfd,5000);
clilen = sizeof(cli_addr);
while (1) {
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) {
perror("ERROR on accept");
exit(1);
}
/* Create child process */
pid = fork();
if (pid < 0) {
perror("ERROR on fork");
exit(1);
}
if (pid == 0) {
/* This is the client process */
close(sockfd);
doprocessing(newsockfd);
exit(0);
}
else {
close(newsockfd);
}
} /* end of while */
}
void doprocessing (int sock)
{
int n,i;
unsigned int *buffer = malloc(1024);
n = read(sock,buffer,1023);
if (n < 0) {
perror("ERROR reading from socket");
exit(1);
}
printf("Here is the message: %.4x\n",*buffer);
n = write(sock,"MCGP",18);
if (n < 0) {
perror("ERROR writing to socket");
exit(1);
}
free(buffer);
}
最佳答案
您的代码中有很多错误:
clien = sizeof(cli_addr);
需要在accept()
调用上方的while
循环内移动。unsigned int *buffer
应该是unsigned char *buffer
。当您只期望 70 个字节时,为什么要读取 1023 个字节?
您需要在循环中调用
read()
,直到您实际接收到您期望的所有字节。read()
返回的字节数可能少于请求的字节数。 TCP 是一个字节流,它没有消息边界的概念,读取将返回当前可用的任何字节,因此它将返回 至少 1 个字节 up to 所请求的字节数。您的
printf()
调用仅输出buffer
的前 4 个字节,而不是输出buffer
的全部内容>。read()
的返回值告诉您实际收到了多少字节。循环遍历buffer
,单独输出每个字节。write(sock,"MCGP",18)
是缓冲区溢出,因为您只传递 5 个字节(4 个字符和空终止符)但告诉它发送 18字节代替。
试试这个:
void doprocessing (int sock);
int main( int argc, char *argv[] ) {
int sockfd, newsockfd, portno;
struct sockaddr_in serv_addr, cli_addr;
socklen_t clilen;
int pid;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR creating socket");
exit(1);
}
/* Initialize socket structure */
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = 14064;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
/* Now bind the host address using bind() call.*/
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR on bind");
exit(1);
}
/* Now start listening for the clients, here
* process will go in sleep mode and will wait
* for the incoming connection
*/
if (listen(sockfd, SOMAXCONN) < 0) {
perror("ERROR on listen");
exit(1);
}
while (1) {
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) {
perror("ERROR on accept");
exit(1);
}
/* Create child process */
pid = fork();
if (pid < 0) {
perror("ERROR on fork");
exit(1);
}
if (pid == 0) {
/* This is the client process */
close(sockfd);
doprocessing(newsockfd);
exit(0);
}
else {
close(newsockfd);
}
} /* end of while */
}
void doprocessing (int sock)
{
int n, i;
unsigned char buffer[70], *p = buffer;
size_t len = 70;
do {
n = read(sock, p, len);
if (n < 0) {
perror("ERROR reading from socket");
exit(1);
}
if (n == 0) {
perror("DISCONNECTED unexpectedly");
exit(1);
}
p += n;
len -= n;
}
while (len > 0);
printf("Here is the message: ");
for (i = 0; i < 70; ++i)
printf("%.02x", buffer[i]);
printf("\n");
n = write(sock, "MCGP", 4);
if (n < 0) {
perror("ERROR writing to socket");
exit(1);
}
}
关于c - 未收到完整数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41492786/