gpt4 book ai didi

c - 非终止 while 循环,同时使用 recv

转载 作者:太空宇宙 更新时间:2023-11-03 23:22:48 25 4
gpt4 key购买 nike

我正在尝试从客户端程序接收一条大消息,两者都使用 SOCK_STREAM 套接字,因此,我必须在 recv 调用中使用 while 循环。但是,它卡住了,并且似乎没有在循环内打印任何内容。

这是服务器的代码

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <arpa/inet.h>

#define BUFSIZE 1024
extern int errno;
void error(char *msg)
{
perror(msg);
exit(0);
}

int main(int argc, char *argv[])
{
int sock, newsock, len, fromlen, n;
unsigned short port;
struct sockaddr_in server, from;
char buffer[BUFSIZE];
char *msg = "I Got your message";

if (argc < 2) {
fprintf(stderr,"usage %s portnumber\n",argv[0]);
exit(0);
}
port = (unsigned short) atoi(argv[1]);
sock=socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) error("Opening socket");
server.sin_family=AF_INET;
server.sin_addr.s_addr=INADDR_ANY;
server.sin_port=htons(port);
len=sizeof(server);
if (bind(sock, (struct sockaddr *)&server, len) < 0)
error("binding socket");
fromlen=sizeof(from);
if (listen(sock,5) < 0)
error("listening");

// accept connections loop
while (1) {
newsock=accept(sock, (struct sockaddr *)&from, &fromlen);
if (newsock < 0) error("Accepting");
printf("A connection has been accepted from %s\n",
inet_ntoa((struct in_addr)from.sin_addr));

// receive long messages loop
while ((n = recv(newsock,buffer,BUFSIZE-1,0)) > 0){
buffer[n] = '\0';
printf("\n message: \n%s\n", buffer);
}

len = strlen(msg);
n = send(newsock,msg,len,0);
if (n < len) error("Error writing");

if (close(newsock) < 0) error("closing");
}
return 0; // we never get here
}

这是客户端的代码

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h> /* for atoi */

char *msg = "Very long message";
void error(char *msg)
{
perror(msg);
exit(0);
}

int main(int argc, char *argv[])
{
int sock, n;
unsigned short port;
struct sockaddr_in server;
struct hostent *hp;
char buffer[1024];

if (argc != 3) {
printf("Usage: %s server port\n", argv[0]);
exit(1);
}
sock= socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) error("Opening socket");

server.sin_family = AF_INET;
hp = gethostbyname(argv[1]);
if (hp==NULL) error("Unknown host");
memcpy((char *)&server.sin_addr,(char *)hp->h_addr,
hp->h_length);
port = (unsigned short)atoi(argv[2]);
server.sin_port = htons(port);
if (connect(sock, (struct sockaddr *)&server, sizeof server) < 0)
error("Connecting");
n = send(sock, msg, strlen(msg),0);
printf("sent %d bytes\n", n);
if (n < strlen(msg))
error("Writing to socket");

n = recv(sock, buffer, 1023,0);
if (n < 1) error("reading from socket");
buffer[n]='\0';
printf("The message from the server is %s\n",buffer);
if (close(sock) < 0) error("closing");
printf("Client terminating\n");

return 0;
}

最终目标是在服务器端接收完整的消息,然后向客户端发送确认消息已收到。

最佳答案

这个条件:

 (n = recv(newsock,buffer,BUFSIZE-1,0)) > 0

将始终为真,除非远程关闭套接字或系统调用返回错误。否则,如果客户端没有发送数据,它将阻塞。

在 STREAM 套接字上,您必须在不做任何假设的情况下期待一个字节流,它将如何在对 recv() 的多次调用中分块。一种常见的解决方案是首先传输(和接收)长度信息,然后调用 recv 直到总共接收到恰好 length 个字节。

您的特殊情况的另一个选项(“快速修复”)可能是在发送大消息后关闭客户端套接字的发送方向:

shutdown(fd, SHUT_WR);

之后,recv 系统调用确实返回 0,服务器可以发送确认。但是,客户端在调用 shutdown() 后将无法发送数据。

关于c - 非终止 while 循环,同时使用 recv,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34751399/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com