这个作业已经布置挺久了,最开始两天只是完成了框架内容的填充(框架由老师提供),解决了各种报错,但是陷入了一个更烦的阶段——有很多看不见的错误。前面放弃了一段时间,这两天突发奇想回来反工一下,还好功夫不负有心人,做了两天总算完成了。
目录
程序介绍
该程序分为了客户端和服务端两端,通过网络交互进行查询;前面加入了登录和注册的操作,登录成功以后才能进行查询单词的操作。对于登录和注册的操作利用了数据库(sqlite3)的操作,实现数据的保存,不至于每次都需要先重新注册才能登录。
首先客户端和服务端的搭建
是网络交互的第一步,套接字的创建,网络信息的绑定,网络的连接建立。
客户端:先创建套接字文件,然后声明自己的主机信息(包括网络地址,端口号,交互网络类型)再声明想要连接的服务端的主机信息。最后向客户端发送连接请求。
服务端:也是先创建套接字文件,然后声明自己的主机信息,再进行数据监听,最后从监听到的客户端中提取第一个客户进行连接操作并创建新的套接字文件。
实现代码如下:
sockfd = socket(AF_INET,SOCK_STREAM,0); //选择TCP交互,ipv4网络
struct sockaddr_in serveraddr;
serveraddr.sin_family=AF_INET; //本机信息
serveraddr.sin_port=htons(8888);
serveraddr.sin_addr.s_addr=inet_addr("192.168.3.143");
bind(serverfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr)); //绑定信息
//连接分两种
//客户端
connect(sockfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr));
//服务端
listen(serverfd,10); //监听
clientfd=accept(serverfd,(struct sockaddr *)&clientaddr,&sizeof(serveraddr));//连接
另外为了实现登录和注册的操作服务端还多了一步 —— 数据库的打开和数据库表的创建,用来存储和判断用户的账号和密码
实现代码:
sqlite3 *db;
if( sqlite3_open("./mydict.db",&db) != SQLITE_OK ) //打开数据库文件
{
printf( "%s\n", sqlite3_errmsg(db) );
return -1;
}
sqlite3_exec(db,"create table user(name text not null,passwd text not null)",NULL,NULL,NULL); //在数据库文件中创建表和表内的项
登录注册界面
该步比较容易犯错的就是对于数据库的调用,输入数据和查询数据。最开始我遇到的问题主要是对于账号和密码的输入到字符串中,然后将其执行数据语句,并且进行判断账号是否存在或者密码是否正确。
我实现的操作:匹配用户名,查询用户名是否存在,输入数据到数据库,匹配用户账号和密码,判断其是否正确。对于匹配时我使用的是给函数传递一个参数n的地址,然后在函数里进行查看数据库的返回数据,如果有数据就给这个n的地址返回1,没有数据就返回0。这样就可以根据注册时匹配用户是否存在和登录时用户和密码是否正确来进行操作了。注册时需要没有数据才能代表可以注册,所以判断返回值是否为0来进行操作;而登陆时需要判断的就是n是否为1了。这样就能使用一个函数,一个参数进行两套操作。
具体代码有点烦杂就不另外贴出了,整体代码放在最后大家可以进行观看。
查询界面
该步整体来说比较简单,只是是实现了一个读取文档内容然后和用户输入的单词进行匹配,但是有一点容易整错,在词典中有很多相同的单词,很大可能你查找到的单词不是需要解释的单词,而是别的单词的解释中的单词。
对于该问题我的解决办法是:进行读取判断,每次只读取一个字符,判断是否是换行符 ‘\n’,如果是,代表下一个字符一定是单词的第一个字母;所以直接读取接收到的单词长度的内容,进行和接收到的单词进行匹配,同时也判断一下下一个字符是否为空格,不然也容易造成匹配错误,你查询的单词是其他单词的前几个字母;这样判断下来如果匹配成功则表示单词找到了,然后通过fgets的特性——一次读取一行,遇到换行符则结束本次读取;获取该单词的意思,最后发送给客户端就完成了查询的操作。
编写的时候遇到的其他问题:
首先说一个比较烦的问题,很多时候总是莫名其妙的就出来了。就是输入停不下来,后续的代码不执行。这个问题困住我挺长时间的,我认为是因为上一个输入的句子结束了下一次输入的语句直接获取了上一句没有获取的类容,比如回车啥的,导致输入直接结束。最后使用的是这个 fflash(stdin) 清空缓存来解决的。清空了上一次输入的东西,避免了对一下一个输入语句的影响。
另外还有一个遇到的问题,这个问题上文我也提到了,就是数据库的匹配问题,数据库语句子啊程序中执行的时候那个函数(exec)返回值是针对于这个函数是否成功执行的,没有办法得到我们想要的是否匹配成功的结果。