下面的程序是通过对输入进行判断,来决定输出内容的。
# include
#include
int main(){
printf("请输入: ");
char buf[1024];
//这里想通过判断输入是否是quit来决定是否完成阅读
if (fgets(buf, sizeof(buf), stdin) != NULL && (strcmp(buf, "quit"))){
printf("欢迎阅读本文章\n");
for (int i = 0;i < 1024;i++){
//打印每个字符的内容
printf("%d ",buf[i]);
}
}
else{
printf("您已经阅读完成本文了,点一下关注哈\n");
}
printf("\n");
}
但是当输入quit的时候,没有走else流程。运行结果居然是是第一个输出。通过打印出来的buf中的字符来看,发现多了个10,因此buf比"quit"要大,也就是strcmp的返回结果是10,为真,所以会走if的流程。
通过上面的分析,可以看出,在这篇文章中,想通过输入quit来关闭socket的实现是有问题的。可以通过另一个函数完美解决这个问题-strncmp。
原型:strcmp(str1,str2);
功能:比较两个字符串,如果两个字符串相等,则返回0;若str1大于str2(对于大于的理解,是指从两个字符串的第一个字符开始比较,若两个字符相同,则继续比较,若发现两个字符不相等,且str1中该字符的ASCII码大于str2中的,则表示str1大于str2),返回一个正数(这个正数不一定是1);若str1小于str2,返回一个负数(不一定是-1);若字符串str1的长度大于str2,且str2的字符与str1前面的字符相同,则也相对于str1大于str2处理
原型2:strncmp(str1,str2,n);
功能2:比较两个字符串的前n个字符
重新写下客户端的代码
/*************************************************************************
> File Name: client.c
> Author: 无情剑客
> Mail: [email protected]
> Created Time: 2020年07月01日 星期三 21时44分37秒
************************************************************************/
#include
#include
#include
#include
#include
#include
#include
#define PORT 6666
#define MAXDATASIZE 2048
int main(int argc, char *argv[])
{
if(argc != 2)
{
fprintf(stderr, "请您输入ip地址!\n");
exit(1);
}
int sockfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
const char *server_ip = argv[1]; //从命令行获取输入的ip地址,此处没有对ip地址进行检验
struct sockaddr_in serveraddr;
bzero(&serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(PORT);
inet_pton(AF_INET, server_ip, &serveraddr.sin_addr);
connect(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr));
printf("=====================服务器链接成功=====================\n");
char buf[MAXDATASIZE];
memset(buf, 0 , sizeof(buf));
printf("请输入: ");
//判断输入的内容是否是quit,如果输入quit,则关闭连接
while(fgets(buf, sizeof(buf), stdin) != NULL && (strncmp(buf, "quit", 4)))
{
send(sockfd, buf, sizeof(buf), 0);
memset(buf, 0, sizeof(buf));
recv(sockfd, buf, sizeof(buf), 0);
printf("服务器说: ");
fputs(buf, stdout);
memset(buf, 0, sizeof(buf));
printf("请输入: ");
}
printf("客户端将要被关闭,下次再见\n");
close(sockfd);
return 0;
}
服务器端代码可参考这篇文章。
开启wireshark,来进行一次完整的抓包。
因为服务iqi地址是127.0.0.1。本地环回地址,所以使用Loopback:lo接口。如果不是本地的服务器,需要选择相应的网卡接口。下面两个图展示了TCP的三次握手和四次挥手。