【发布时间】:2021-12-03 01:26:31
【问题描述】:
我有一个简单的 C 语言服务器和客户端。
我要实现的功能的步骤是:
-
服务器向客户端发送一个字符“%”并打印在客户端的屏幕上。
-
客户端然后输入一条消息,该消息将发送到服务器并打印在服务器的屏幕上,上面写着“客户端:(来自客户端的消息)”。
-
服务器最终向客户端发送一条“收到消息”的消息,并将其打印在客户端的屏幕上。
-
返回步骤 1。
我为客户端添加了一个名为 valid 的指示器,用于告诉服务器缓冲区(来自客户端的消息)何时真正有效,以防止 客户端写入 和 服务器读取不同步。
但是,我得到的结果是这样的:
提前谢谢你!
客户端代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
void error(const char *msg){
perror(msg);
exit(1); //terminate program
}
int main(int argc, char *argv[]){
int sockfd/*(file descriptor)*/, portno, n;
char buffer[255];
int valid = 0;
struct sockaddr_in serv_addr, cli_addr;
portno = 1234;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0){
error("Error opening socket.");
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(1234);
if( connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0 ){
error("Connection failed");
}
S: bzero(buffer, 255);
n = read(sockfd, buffer, 255);
if(n < 0){
error("Error reading from socket");
}
printf("%s", buffer);
bzero(buffer, 255);
fgets(buffer, 255, stdin);
// valid is set to 1 and sent to server
// when the message in buffer is actually typed in and meant to be sent to the server
valid = 1;
write(sockfd, &valid, sizeof(valid));
write(sockfd, buffer, strlen(buffer));
if(strncmp("exit", buffer, 4) == 0){
goto Q;
}
bzero(buffer, 255);
n = read(sockfd, buffer, 255);
if(n < 0){
error("Error reading from socket");
}
printf("%s", buffer);
goto S;
Q: printf("You have chosen to exit. Exit successful\n");
close(sockfd);
return 0;
}
服务器代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
void error(const char *msg){
perror(msg);
exit(1); //terminate program
}
int main(int argc, char *argv[]){
int sockfd/*(file descriptor)*/, newsockfd, portno, n;
char buffer[255];
int valid = 0;
int count = 0;
struct sockaddr_in serv_addr, cli_addr;
socklen_t clilen;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0){
error("Error opening socket.");
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(1234);
if(bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){
error("Building failed");
}
listen(sockfd, 5); //integer stands for max clients
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if(newsockfd < 0){
error("Error on accept");
}
int num1, num2, ans, choice;
S:
valid = 0;
bzero(buffer, 255);
if(count == 0){
count++;
strcpy(buffer, "********************************\n** Welcome to the BBS server. **\n********************************\n%");
}else{
strcpy(buffer, "% ");
}
n = write(newsockfd, buffer, strlen(buffer));
if(n < 0){
error("Error writing to socket");
}
M:
// check if the message from client (buffer) is valid
read(newsockfd, &valid, sizeof(int));
// if not, return to M
if(valid == 0){
goto M;
}
// continue if valid
bzero(buffer, 255);
read(newsockfd, buffer, strlen(buffer));
if(strncmp("exit", buffer, 4) == 0){
goto Q;
}
printf("Client: %s\n", buffer);
bzero(buffer, 255);
strcpy(buffer, "Message received.\n");
n = write(newsockfd, buffer, strlen(buffer));
if(n < 0){
error("Error writing to socket\n");
}
goto S;
Q: close(newsockfd);
close(sockfd);
return 0;
}
【问题讨论】:
-
在
printf()之后使用fflush(stdout);。输出是行缓冲的,因此如果它不以换行符结尾,您将看不到任何内容。 -
截图中有
Command received,但我在代码中没有看到。因此,这与产生该输出的代码不同。 -
我刚刚编辑更新了正确的照片,谢谢提醒。
-
不要用
goto语句构造循环。goto有几个合理的用例,但它们并不常见,循环不是其中之一。请改用for、while和do ... while语句,必要时使用break和/或continue。有时将您的代码分解为多个函数也会有所帮助。 -
我尝试按照您的建议使用 fflush(stdout),但是在客户端进行一次写入后,服务器上仍然出现 3 个“客户端:”,客户端上出现了 2 个“收到消息”。