gpt4 book ai didi

c - 只回显第一个数据包的TCP回显服务器(C语言)

转载 作者:可可西里 更新时间:2023-11-01 02:33:42 25 4
gpt4 key购买 nike

我用 C 语言为 TCP 服务器编写了一些代码,它可以回显它收到的任何内容。问题是当我第一次发送数据时它回显它,下次服务器发回我发送的第一个数据包。日志看起来像:

Client Send : Packet1
Server reply : Packet1
Client Send : Packet2
server reply : Packet1

服务端代码如下:

int main(int argc, char** argv) {
int listenfd,connfd;
pid_t childpid;
socklen_t clilen;
struct sockaddr_in servaddr,cliaddr;
listenfd = socket(AF_INET,SOCK_STREAM,0);
printf("Socket listenfd : %d with %d And %d\n",listenfd,AF_INET,SOCK_STREAM);
bzero(&servaddr, sizeof(servaddr));

servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
printf("Server address: %d\n",servaddr.sin_addr.s_addr);
bind(listenfd, (SA*) &servaddr, sizeof(servaddr));
printf("Listened: %d\n",listenfd);
listen(listenfd,LISTENQ);
printf("After Listening: %d\n",listenfd);
int num=0;
for( ; ; ){
clilen=sizeof(cliaddr);
connfd = accept(listenfd, (SA*) &cliaddr,&clilen);
printf("Client no. %d connected\n",++num);
if( (childpid=fork())==0){
close(listenfd);
echo(connfd);
exit(0);
printf("Client no. %d Terminated\n",++num);
}
close(connfd);
}
return (EXIT_SUCCESS);
}

还有我的 echo 函数:

void echo(int sockfd) {
ssize_t n;
char buf[MAXLINE];
again:
while ( (n = read(sockfd, buf, MAXLINE)) > 0)
writen(sockfd, buf, n);
if (n < 0 && errno == EINTR)
goto again;
else if (n < 0)
printf("read error");
}

客户端主要代码:

int main(int argc, char** argv) {
int sockfd;
struct sockaddr_in servaddr;

sockfd= socket(AF_INET,SOCK_STREAM,0);
bzero(&servaddr,sizeof(servaddr));

servaddr.sin_family = AF_INET;
servaddr.sin_port= htons(SERV_PORT);
inet_pton(AF_INET,"0.0.0.0",&servaddr.sin_addr);
printf("%d , %d \n",sockfd,servaddr.sin_addr.s_addr);
connect(sockfd, (SA*) &servaddr,sizeof(servaddr));
printf("%d\n",sockfd);
replyBack(stdin,sockfd);

printf("RETURN\n");
return (EXIT_SUCCESS);
}

replyBack 函数:

void replyBack(FILE *fp, int sockfd) {
char sendline[MAXLINE], recvline[MAXLINE];
printf("ENTER YOUR ECHOED: \n");
while (fgets(sendline, MAXLINE, stdin) != NULL) {
write(sockfd, sendline, sizeof(sendline));

if (read(sockfd, recvline, MAXLINE) == 0)
{
printf("str_cli: server terminated prematurely");
exit(-1);
}
fputs(recvline, stdout);

}
}

最佳答案

好吧,让我们看一下您的这部分代码:

printf("After Listening: %d\n",listenfd);
int num=0;
for( ; ; ){
clilen=sizeof(cliaddr);
connfd = accept(listenfd, (SA*) &cliaddr,&clilen);
printf("Client no. %d connected\n",++num);
if( (childpid=fork())==0){
close(listenfd);
echo(connfd);
exit(0);
printf("Client no. %d Terminated\n",++num);
}
close(connfd);
}

调用 exit 退出您的应用程序,因此它后面的 printf 将永远不会执行。次要,但值得指出。

此外,在“子”进程中,您不应该关闭您的监听套接字。它应该使用的唯一套接字是客户端连接,所以你应该有更多的东西:

if ( (childpid = fork ()) == 0 ) {
echo ( connfd );
close ( connfd );
printf ( "Client no %d terminated.\n", num ); /* Don't use the ++ here or your count will be off */
exit ( 0 );
}

现在让我们看看您的回显代码:

void echo(int sockfd) {
ssize_t n;
char buf[MAXLINE];
again:
while ( (n = read(sockfd, buf, MAXLINE)) > 0)
writen(sockfd, buf, n);
if (n < 0 && errno == EINTR)
goto again;
else if (n < 0)
printf("read error");
}

必须记住对 readwrite 的调用可能会阻塞(因为我没有看到您将套接字设置为非阻塞 IO),并且 write 调用时可能不会发送整个缓冲区,因此您需要在此处检查更多内容。

void
echo ( int sockfd )
{
ssize_t bytes_in, bytes_out, bytes_remaining;
int write_err;
char buf[MAXLINE];
char * send_start_pos;
while ( 1 ) {
bytes_in = read ( sockfd, buf, MAXLINE );
if ( bytes_in < 1 ) {
if ( errno == EINTR )
continue;
break; /* other error occurred, or EOF (0 bytes read) */
}
bytes_remaining = bytes_in;
send_start_pos = buf;
write_err = 0;
while ( ( bytes_remaining > 0 ) && !( write_err ) ) {
bytes_out = write ( sockfd, send_start_pos, bytes_remaining );
if ( bytes_out < 0 ) {
if ( errno == EINTR )
continue;
write_err = 1;
break;
}
bytes_remaining -= bytes_out;
send_start_pos += bytes_out;
}
if ( write_err )
break;
}
}

一旦您的echo 函数退出,套接字将在调用函数中关闭。通常,我会建议在 echo 函数中关闭套接字,除非您之后需要它。我几乎肯定会建议在发生错误时将其关闭,但这同样取决于您。

顺便说一句,远离 goto ...它有其目的,但在大多数情况下,编写良好的代码很少使用它。

关于c - 只回显第一个数据包的TCP回显服务器(C语言),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5171545/

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