我在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);
}
答案 0 :(得分:3)
您的代码中存在大量错误:
clilen = sizeof(cli_addr);
需要在while
来电之上的accept()
循环内移动。
unsigned int *buffer
应该是unsigned char *buffer
。
当你只期望70个字节时,为什么要读取1023个字节?
您需要在循环中调用read()
,直到您实际收到所需的所有字节为止。 read()
可以返回比请求的字节少的字节。 TCP是字节流,它没有消息边界的概念,读取将返回当前可用的任何字节,因此它将返回至少 1字节直到所请求的字节数。
您的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);
}
}