项目和格式要求
项目要求:
1. 登录注册功能,不能重复登录,重复注册
2. 单词查询功能
3. 历史记录功能,存储单词,意思,以及查询时间
4. 基于TCP,支持多客户端连接
5. 采用数据库保存用户信息与历史记录
6. 将dict.txt的数据导入到数据库中保存。
7. 按下ctrl+c退出客户端后,注销该客户端的登录信息
格式要求:
1. main函数只跑逻辑,不允许
流程图
代码
function.h
#ifndef __FUNCTION_H__
#define __FUNCTION_H__
//打印新的错误宏函数
#define ERR_MSG(msg) do{\
fprintf(stderr, "__%d__", __LINE__);\
perror(msg);\
}while(0)
#define PORT 8888
#define IP "192.168.239.128"
#include <sqlite3.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <time.h>
//主菜单
void menu();
//登录子菜单
void logon_menu();
//登录
int logon(int sfd);
//注册
int regis(int sfd);
//单词查询
int word(int sfd);
//历史记录
int history(int sfd);
//用户下线
int notlogin(sqlite3 *db, char *user);
//数据库初始化
sqlite3 *init_db();
//服务器客户端交互
int interact(int newfd, sqlite3 *db, struct sockaddr_in cli);
#endif
function.c
#include "function.h"
//主菜单
void menu()
{
printf("—————————————————\n");
printf("1、登录\n");
printf("2、注册\n");
printf("0、退出\n");
printf("—————————————————\n");
printf("请输入序号:");
}
//登录子菜单
void logon_menu()
{
printf("—————————————————\n");
printf("1、单词查找\n");
printf("2、历史记录\n");
printf("0、退出登录\n");
printf("—————————————————\n");
printf("请输入序号:");
}
//登录
int logon(int sfd)
{
char user[18];
char pass[18];
char request[128];
char choose;
ssize_t res;
printf("请输入用户名:");
fgets(user, sizeof(user), stdin);
user[strlen(user)-1] = 0;
printf("请输入密码:");
fgets(pass, sizeof(pass), stdin);
pass[strlen(pass)-1] = 0;
//发送登录请求给服务器
sprintf(request, "%c%c%s%c%s%c", 'L', 0, user, 0, pass, 0);
if(send(sfd, request, 2+strlen(user)+1+strlen(pass)+1, 0) < 0)
{
ERR_MSG("send");
return -1;
}
//接收服务返回的信息
bzero(request, sizeof(request));
res = recv(sfd, request, sizeof(request), 0);
if(res < 0)
{
ERR_MSG("recv");
return -1;
}
else if(0 == res)
{
printf("服务器已关闭\n");
return -1;
}
printf("%s\n", request);
//接收服务器发来的应答
if(request[0] == 'Y')
{
printf("登录成功\n");
//进入登录子菜单
while(1)
{
logon_menu();
scanf("%c", &choose);
while(getchar()!=10);
switch(choose)
{
case '1':
{
//单词查询
word(sfd);
break;
}
case '2':
{
//历史记录
history(sfd);
break;
}
case '0':
{
//退出登录并向服务器发送下线请求
//向服务器发送下线信息
sprintf(request, "%c%c%s%c", 0, 'Q', user, 0);
if(send(sfd, request, 2+strlen(user)+1, 0) < 0)
{
ERR_MSG("send");
return -1;
}
break;
}
default:
{
printf("输入序号有误,请重新输入\n");
break;
}
}
}
}
else if(request[0] == 'N')
{
printf("登录失败,输入的账号或密码有误\n");
}
else if(request[0] == 'L')
{
printf(" 该账号已登录,请勿重复登录\n");
}
return 0;
}
//注册
int regis(int sfd)
{
char user[18] = "";
char pass[18] = "";
char request[128] = "";
ssize_t res = 0;
printf("请输入用户名:");
fgets(user, sizeof(user), stdin);
user[strlen(user)-1] = 0;
printf("请输入密码:");
fgets(pass, sizeof(pass), stdin);
pass[strlen(pass)-1] = 0;
//向服务器发送注册请求
sprintf(request, "%c%c%s%c%s%c", 'R', 0, user, 0, pass, 0);
if(send(sfd, request, sizeof(request), 0) < 0)
{
ERR_MSG("send");
return -1;
}
//接收服务返回的信息
bzero(request, sizeof(request));
res = recv(sfd, request, sizeof(request), 0);
if(res < 0)
{
ERR_MSG("recv");
return -1;
}
else if(0 == res)
{
printf("服务器已关闭\n");
return -1;
}
//接收服务器发来的应答
if(request[0] == 'Y')
{
printf("注册成功!\n");
}
else if(request[0] == 'N')
{
printf("注册失败,该用户名已存在\n");
}
return 0;
}
//单词查询
int word(int sfd)
{
char request[128] = "";
char word[18] = "";
ssize_t res;
while(1)
{
printf("请输入要查询的单词:");
bzero(word, sizeof(word));
fgets(word, sizeof(word), stdin);
word[strlen(word)-1] = 0;
//向服务器发送查询单词的请求
sprintf(request,"%c%c%s",'W', 0, word);
if(send(sfd,request, 2+strlen(word)+1, 0) < 0)
{
ERR_MSG("send");
return -1;
}
//接收服务器发来的应答
bzero(request, sizeof(request));
res = recv(sfd, request, 2, 0);
if(res < 0)
{
ERR_MSG("recv");
return -1;
}
else if(0 == res)
{
printf("服务器已关闭\n");
return -1;
}
if(request[0] == 'Y')
{
while(1)
{
//给服务器发送应答
bzero(request, sizeof(request));
sprintf(request,"%c%c", 'Y', 0);
if(send(sfd, request, 2, 0) < 0)
{
ERR_MSG("send");
return -1;
}
//接收服务器发送过来的消息
bzero(request, sizeof(request));
res = recv(sfd, request, sizeof(request), 0);
if(res < 0)
{
ERR_MSG("recv");
return -1;
}
else if(0 == res)
{
printf("服务器已关闭\n");
return -1;
}
if(request[0] == 'N')
{
//传输结束
break;
}
//显示查询结果
char *result = request+strlen(request)+1;
printf("%-10s\t%-s\n", request, result);
}
}
else if(request[0] == 'N')
{
printf("未找到该单词\n");
}
}
return 0;
}
//查询历史记录
int history(int sfd)
{
char request[128]="";
ssize_t res;
//向服务器发送查询历史记录请求
sprintf(request,"%c%c",'H', 0);
if(send(sfd, request, 2, 0) < 0)
{
ERR_MSG("send");
return -1;
}
//接收服务返回的应答信息
bzero(request, sizeof(request));
res = recv(sfd, request, 2, 0);
if(res < 0)
{
ERR_MSG("recv");
return -1;
}
else if(0 == res)
{
printf("服务器已关闭\n");
return -1;
}
if(request[0] == 'Y')
{
while(1)
{
bzero(request, sizeof(request));
//给服务器发送应答
sprintf(request, "%c%c",'Y', 0);
if(send(sfd, request, 2, 0) < 0)
{
ERR_MSG("send");
return -1;
}
//接收服务器发送过来的消息
bzero(request, sizeof(request));
res = recv(sfd, request, sizeof(request), 0);
if(res<0)
{
ERR_MSG("recv");
return -1;
}
else if(0 == res)
{
printf("服务器已关闭\n");
return -1;
}
if(request[0] == 'N')
{
//传输完成
break;
}
char *result = request+strlen(request)+1;
char *time = result+strlen(result)+1;
printf("%-18s%-30s\t%-16s\n", request, result, time);
}
}
else if(request[0] == 'N')
{
//历史记录
printf("历史记录为空\n");
}
return 0;
}
//用户下线
int notlogin(sqlite3 *db, char *user)
{
//将数据库中该用户状态信息更新为下线
char sql[200] = "";
char *errmsg = NULL;
char **pres = NULL; //存储查询结果的首地址
int row = 0; //查询结果的行数
int column = 0; //查询结果的列数
//查询用户状态
sprintf(sql,"select * from user where user=\"%s\" and state=%d;", user, 'L');
if(sqlite3_get_table(db,sql,&pres,&row,&column,&errmsg) != SQLITE_OK)
{
fprintf(stderr, "__%d__ sqlite3_get_table:%s\n", __LINE__, errmsg);
return -1;
}
if(row == 1)
{
bzero(sql,sizeof(sql));
sprintf(sql, "update user set state=%c where user='%s'", 'N', user);
if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "__%d__ error_code:%d sqlite3_exec:%s\n", __LINE__, sqlite3_errcode(db), errmsg);
return -1;
}
printf("用户:%s 下线\n", user);
}
return 0;
}
sqlite3 *init_db()
{
sqlite3 *db=NULL;
//打开数据库
if(sqlite3_open("./my.db", &db) != SQLITE_OK)
{
fprintf(stderr, "__%d__ sqlite3_open:%s\n", __LINE__,
sqlite3_errmsg(db));
return NULL;
}
//创建账户信息表格
char sql[400] = "create table if not exists users (user char primary key,pass char,state char)";
char* errmsg = NULL;
if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__,errmsg);
return NULL;
}
//创建历史记录表格
sprintf(sql,"create table if not exists record (user char,word char,mean char,time char)");
if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__,errmsg);
return NULL;
}
//用户表全部更新为下线状态
sprintf(sql, "update users set state=\"%c\" where state=\"%c\";", 'Q', 'L');
if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "__%d__ error_code:%d sqlite3_exec:%s\n", __LINE__,sqlite3_errcode(db),errmsg);
return NULL;
}
printf("数据库初始化完成\n");
return db;
}
//服务器客户端交互
int interact(int newfd, sqlite3 *db, struct sockaddr_in cli)
{
char user[18] = ""; //用户名
char pass[18] = ""; //密码
char request[128] = ""; //客户端发来的请求
char type; //请求类型
ssize_t res = 0;
while(1)
{
//接收客户端发送来的信息
bzero(request, sizeof(request));
res = recv(newfd, request,sizeof(request), 0);
if(res < 0)
{
ERR_MSG("recv");
return -1;
}
else if(0 == res)
{
notlogin(db,user);
printf("[IP:%s 端口:%d]断开连接\n",inet_ntoa(cli.sin_addr),ntohs(cli.sin_port));
return -1;
}
//拆解请求
type = request[0];
//printf("%c\n", type);
switch(type)
{
case 'L':
{
//登录信息
bzero(user, sizeof(user));
strcpy(user, request+2); //用户名
strcpy(pass, request+2+strlen(user)+1); //密码
//查询数据库中是否存在该用户
char sql[200] = "";
char **pres = NULL; //存储查询结果的首地址
int row = 0; //查询结果的行数
int column = 0; //查询结果的列数
char *errmsg = NULL;
sprintf(sql, "select * from users where user=\"%s\" and pass =\"%s\"", user, pass);
if(sqlite3_get_table(db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
{
fprintf(stderr,"__%d__ sqlite3_get_table:%s\n",__LINE__,errmsg);
return -1;
}
if(row == 1)
{
//存在该用户名
//判断密码是否正确
//判断是否重复登录
sprintf(sql,"select * from users where user=\"%s\" and pass=\"%s\" and state=\"%c\";",user,pass,'Q');
if(sqlite3_get_table(db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "__%d__ sqlite3_get_table:%s\n", __LINE__, errmsg);
return -1;
}
if(row == 1)
{
//发送信息给客户端
bzero(request, sizeof(request));
sprintf(request, "%c%c", 'Y', 0);
// printf("%s\n", request);
if(send(newfd, request, 2, 0) < 0)
{
ERR_MSG("send");
return -1;
}
//更新用户状态为上线
bzero(sql, sizeof(sql));
sprintf(sql, "update users set state=\"%c\" where user='%s'", 'L', user);
if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "__%d__ error_code:%d sqlite3_exec:%s\n", __LINE__,sqlite3_errcode(db),errmsg);
return -1;
}
printf("用户:%s 已上线\n",user);
}
else
{
//发送已登录消息给客户端
bzero(request, sizeof(request));
sprintf(request,"%c%c", 'L', 0);
// printf("%s\n", request);
if(send(newfd, request, 2, 0) < 0)
{
ERR_MSG("send");
return -1;
}
}
}
else
{
//用户名不存在或密码错误
//发送登录失败信息给客户端
bzero(request, sizeof(request));
sprintf(request, "%c", 'N', 0);
// printf("%s\n", request);
if(send(newfd, request, 2, 0) < 0)
{
ERR_MSG("send");
return -1;
}
}
//释放获取到的空间
sqlite3_free_table(pres);
pres = NULL;
}
break;
case 'R':
{
//注册信息
bzero(user,sizeof(user));
strcpy(user, request+2);
strcpy(pass, request+2+strlen(user)+1);
//查询数据库中是否存在该用户名
char sql[200]="";
char **pres = NULL; //存储查询结果的首地址
int row=0; //查询结果的行数
int column=0; //查询结果的列数
char *errmsg = NULL;
sprintf(sql,"select * from users where user=\"%s\";",user);
if(sqlite3_get_table(db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "__%d__ sqlite3_get_table:%s\n", __LINE__, errmsg);
return -1;
}
if(row != 1)
{
//发送可注册信息给客户端
bzero(request, sizeof(request));
sprintf(request, "%c%c", 'Y', 0);
if(send(newfd, request, 2, 0) < 0)
{
ERR_MSG("send");
return -1;
}
//将注册信息写入到数据库
bzero(sql, sizeof(sql));
sprintf(sql, "insert into users values(\"%s\", \"%s\",\"%c\")", user, pass, 'Q');
if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "__%d__ error_code:%d sqlite3_exec:%s\n", __LINE__,sqlite3_errcode(db),errmsg);
return -1;
}
printf("用户:%s 信息已存入数据库\n",user);
}
else
{
//用户名已存在
//发送无法注册信息给客户端
bzero(request, sizeof(request));
sprintf(request, "%c%c", 'N', 0);
if(send(newfd, request, 2, 0) < 0)
{
ERR_MSG("send");
return -1;
}
}
//释放获取到的空间
sqlite3_free_table(pres);
pres = NULL;
}
break;
case 'W':
{
//查询单词信息
char word[18] = "";
char result[18] = "";
strcpy(word, request+2);
//查询数据库中是否存在该单词
char sql[200] = "";
char **pres = NULL; //存储查询结果的首地址
int row = 0; //查询结果的行数
int column = 0; //查询结果的列数
char *errmsg = NULL;
sprintf(sql, "select * from dict where word=\"%s\";", word);
if(sqlite3_get_table(db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "__%d__ sqlite3_get_table:%s\n", __LINE__, errmsg);
return -1;
}
if(row > 0)
{
//存在该单词
bzero(request,sizeof(request));
sprintf(request,"%c%c", 'Y', 0);
if(send(newfd, request, 2, 0) < 0)
{
ERR_MSG("send");
return -1;
}
//接收客户端发送来的应答
bzero(request, sizeof(request));
res = recv(newfd, request, 2, 0);
if(res < 0)
{
ERR_MSG("recv");
return -1;
}
else if(0 == res)
{
notlogin(db, user);
printf("[IP:%s 端口:%d]断开连接\n", inet_ntoa(cli.sin_addr), ntohs(cli.sin_port));
return -1;
}
int i;
bzero(request, sizeof(request));
for(i=column; i<(row+1)*column; i++)
{
if(i%column == 0)
{
//获取单词
bzero(word,sizeof(word));
sprintf(word, "%s", pres[i]);
strcpy(request, word);
}
if(i%column == (column-1))
{
//获取单词意思
bzero(result, sizeof(result));
sprintf(result, "%s", pres[i]);
strcpy(request+strlen(word)+1, result);
if(send(newfd, request, 2+strlen(word)+strlen(result)+1, 0) < 0)
{
ERR_MSG("send");
return -1;
}
//获取查询时间
time_t t = 0;
struct tm *info = NULL;
char record_time[18] = "";
t = time(NULL);
info = localtime(&t);
sprintf(record_time,"%d-%d-%d %d:%d",info->tm_year+1900,\
info->tm_mon+1,info->tm_mday,info->tm_hour,\
info->tm_min);
//将查询记录输入到数据库
bzero(sql,sizeof(sql));
sprintf(sql, "insert into record values(\"%s\", \"%s\",\"%s\",\"%s\")",user,word, result, record_time);
if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "__%d__ error_code:%d sqlite3_exec:%s\n", __LINE__,sqlite3_errcode(db),errmsg);
return -1;
}
printf("用户:%s 查询已记录\n",user);
//接收客户端发送来的应答
bzero(request, sizeof(request));
res = recv(newfd, request, sizeof(request), 0);
if(res < 0)
{
ERR_MSG("recv");
return -1;
}
else if(0 == res)
{
notlogin(db, user);
printf("[IP:%s 端口:%d]断开连接\n",inet_ntoa(cli.sin_addr),ntohs(cli.sin_port));
return -1;
}
if(request[0] == 'Y')
{
bzero(request,sizeof(request));
}
else if(request[0] == 'N')
{
printf("传输中断\n");
break;
}
}
}
//传输完成
printf("用户:%s 查询历史信息已传输\n",user);
bzero(request, sizeof(request));
sprintf(request, "%c%c", 'N', 0);
if(send(newfd, request, 2, 0) < 0)
{
ERR_MSG("send");
return -1;
}
}
else
{
//不存在该单词
bzero(request, sizeof(request));
sprintf(request, "%c%c", 'N', 0);
if(send(newfd, request, 2, 0) < 0)
{
ERR_MSG("send");
return -1;
}
}
//释放获取到的空间
sqlite3_free_table(pres);
pres = NULL;
}
break;
case 'H':
{
//查询历史信息
char record_time[18] = "";
char word[18] = "";
char result[18] = "";
//查询该用户在数据库中是否存在记录
char sql[200]="";
char **pres = NULL; //存储查询结果的首地址
int row = 0; //查询结果的行数
int column = 0; //查询结果的列数
char *errmsg = NULL;
sprintf(sql, "select * from record where user=\"%s\";", user);
if(sqlite3_get_table(db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "__%d__ sqlite3_get_table:%s\n", __LINE__, errmsg);
return -1;
}
if(row > 0)
{
//存在记录
bzero(request, sizeof(request));
sprintf(request, "%c%c", 'Y', 0);
if(send(newfd, request, 2, 0) < 0)
{
ERR_MSG("send");
return -1;
}
//接收客户端发送来的应答
bzero(request, sizeof(request));
res = recv(newfd, request, 2, 0);
if(res < 0)
{
ERR_MSG("recv");
return -1;
}
else if(0 == res)
{
notlogin(db,user);
printf("[IP:%s 端口:%d]断开连接\n", inet_ntoa(cli.sin_addr), ntohs(cli.sin_port));
return -1;
}
int i;
bzero(request, sizeof(request));
for(i=column;i<(row+1)*column;i++)
{
if(i%column == (column-3))
{
//获取单词信息
bzero(word, sizeof(word));
sprintf(word, "%s", pres[i]);
strcpy(request, word);
}
if(i%column == (column-2))
{
//获取单词意思
bzero(result, sizeof(result));
sprintf(result, "%s", pres[i]);
strcpy(request+strlen(word)+1, result);
}
if(i%column == (column-1))
{
//获取时间信息
bzero(record_time, sizeof(record_time));
sprintf(record_time, "%s", pres[i]);
//整合记录后发送给客户端
strcpy(request+strlen(word)+strlen(result)+2, record_time);
if(send(newfd, request, strlen(word)+strlen(result)+strlen(record_time)+3,0) < 0)
{
ERR_MSG("send");
return -1;
}
//接收客户端发送来的应答
bzero(request, sizeof(request));
res = recv(newfd, request, sizeof(request), 0);
if(res < 0)
{
ERR_MSG("recv");
return -1;
}
else if(0 == res)
{
notlogin(db, user);
printf("[IP:%s 端口:%d]断开连接\n",inet_ntoa(cli.sin_addr), ntohs(cli.sin_port));
return -1;
}
if(request[0] == 'Y')
{
bzero(request, sizeof(request));
}
else if(request[0] == 'N')
{
printf("传输中断\n");
break;
}
}
}
printf("用户:%s 查询历史信息已传输\n",user);
bzero(request, sizeof(request));
sprintf(request,"%c%c", 'N', 0);
if(send(newfd, request, 2, 0) < 0)
{
ERR_MSG("send");
return -1;
}
}
else
{
//不存在记录
bzero(request, sizeof(request));
sprintf(request, "%c%c", 'N', 0);
if(send(newfd, request, 2, 0) < 0)
{
ERR_MSG("send");
return -1;
}
}
//释放获取到的空间
sqlite3_free_table(pres);
pres = NULL;
}
break;
case 'Q':
{
//处理下线信息
strcpy(user, request+2);
notlogin(db, user);
}
break;
default:
printf("未知信息\n");
}
}
return 0;
}
dictSer.c
#include "function.h"
typedef void (*sighandler_t)(int);
void handler(int sig)
{
//回收僵尸进程
while(waitpid(-1, NULL, WNOHANG) > 0);
}
int main(int argc, const char *argv[])
{
int newfd = 0;
pid_t pid = 0;
sqlite3 *db = init_db();
//捕获17号信号 SIGCHLD
sighandler_t s = signal(17, handler);
if(SIG_ERR == s)
{
ERR_MSG("signal");
return -1;
}
//创建流式套接字
int sfd = socket(AF_INET,SOCK_STREAM,0);
if(sfd<0)
{
ERR_MSG("socket");
return -1;
}
//允许端口快速重用
int reuse = 1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0)
{
ERR_MSG("setsocket");
return -1;
}
//填写服务器地址信息结构体
struct sockaddr_in ser;
ser.sin_family = AF_INET;
ser.sin_port = htons(PORT);
ser.sin_addr.s_addr = inet_addr(IP);
//绑定
if(bind(sfd,(struct sockaddr *)&ser,sizeof(ser))!=0)
{
ERR_MSG("bind");
return -1;
}
//监听
if(listen(sfd,10)!=0)
{
ERR_MSG("listen");
return -1;
}
//保存客户端的地址信息结构体
struct sockaddr_in cli;
socklen_t addrlen = sizeof(cli);
while(1)
{
//父进程
int newfd = accept(sfd,(struct sockaddr *)&cli,&addrlen);
if(newfd<0)
{
ERR_MSG("accept");
return -1;
}
pid = fork();
if(pid>0)
{
close(newfd);
}
else if(0==pid)
{
close(sfd);
//与客户端交互函
interact(newfd,db,cli);
//关闭
close(newfd);
exit(0);
}
else
{
ERR_MSG("fork");
return -1;
}
}
//关闭数据库
if(sqlite3_close(db) !=SQLITE_OK)
{
fprintf(stderr,"__%d__ sqlite3_close:%s\n",__LINE__,sqlite3_errmsg(db));
}
//关闭文件描述符
close(sfd);
return 0;
}
```c
#include "function.h"
int main(int argc, const char *argv[])
{
char choose = 0;
//创建流式套接字
int sfd = socket(AF_INET, SOCK_STREAM, 0);
if(sfd < 0)
{
ERR_MSG("socket");
return -1;
}
//填充要连接的服务器的地址信息结构体
struct sockaddr_in ser;
ser.sin_family = AF_INET;
ser.sin_port = htons(PORT);
ser.sin_addr.s_addr = inet_addr(IP);
//连接服务器 connect
if(connect(sfd, (struct sockaddr*)&ser, sizeof(ser)) < 0)
{
ERR_MSG("connect");
return -1;
}
//主菜单
while(1)
{
system("clear");
menu();
scanf("%c", &choose);
while(getchar()!=10);
switch(choose)
{
case '1':
logon(sfd);
break;
case '2':
regis(sfd);
break;
case '0':
exit(0);
default:
printf("输入错误,请重新输入\n");
}
}
//关闭套接字
close(sfd);
return 0;
}
```#include "function.h"
int main(int argc, const char *argv[])
{
char choose = 0;
//创建流式套接字
int sfd = socket(AF_INET, SOCK_STREAM, 0);
if(sfd < 0)
{
ERR_MSG("socket");
return -1;
}
//填充要连接的服务器的地址信息结构体
struct sockaddr_in ser;
ser.sin_family = AF_INET;
ser.sin_port = htons(PORT);
ser.sin_addr.s_addr = inet_addr(IP);
//连接服务器 connect
if(connect(sfd, (struct sockaddr*)&ser, sizeof(ser)) < 0)
{
ERR_MSG("connect");
return -1;
}
//主菜单
while(1)
{
system("clear");
menu();
scanf("%c", &choose);
while(getchar()!=10);
switch(choose)
{
case '1':
logon(sfd);
break;
case '2':
regis(sfd);
break;
case '0':
exit(0);
default:
printf("输入错误,请重新输入\n");
}
}
//关闭套接字
close(sfd);
return 0;
}
部分结果展示
注册
登录
单词查询
历史记录