3.项目:基于TCP的文件服务
项目需求:
1.编写客户端和服务器
2客户端可以查看服务器端目录中的文件名 opendir readdir
3客户端可以从服务器中下载文件
4客户端可以上传文件给服务器
头文件
#ifndef __DIC_H__
#define __DIC_H__
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <dirent.h>
#include <fcntl.h>
#define MAXSIZE 512
#define ERR_MSG(msg)do{\
fprintf(stderr,"%s failed at line %d.\n",msg,__LINE__);\
}while(0)
#define SUC_MSG(msg)do{\
printf("%s success at line %d.\n",msg,__LINE__);\
}while(0)
//socket related
void create_socket(int*);
void quick_reuse(int*);
void bind_socket(int*,struct sockaddr_in*,int*,int,const char*);
void listen_socket(int*);
void connect_server(int*,struct sockaddr_in*,socklen_t,int,const char*);
int accept_socket(int,struct sockaddr_in*,socklen_t*);
#endif
服务器端
#include "dir.h"
const int serPort = 2305;
const char* serIp = "192.168.10.104";
void zombie_deal(int);
void reveal_content(int,char*);
void show_dir(int);
void recv_from_cli(int);
void deal_client(int,struct sockaddr_in);
int main(int argc, const char *argv[])
{
int sfd;
struct sockaddr_in sin;
int len = sizeof(sin);
struct sockaddr_in cin;
int newfd;
//if a child process dies
if(signal(17,zombie_deal) == SIG_ERR){
ERR_MSG("Receive signal");
return -1;
}
//create socket
create_socket(&sfd);
//allow quick reuse of port
quick_reuse(&sfd);
//bind socket
bind_socket(&sfd,&sin,&len,serPort,serIp);
//turn the socket sfd into a listen fd
listen_socket(&sfd);
while(1){
//create a new fd if a client successfully connected
newfd = accept_socket(sfd,&cin,&len);
if(fork() == 0){
deal_client(newfd,cin);
close(sfd);
}
else{
//每次fork后,cin加入数组,cpid
}
close(newfd);
}
close(sfd);
return 0;
}
客户端
#include "dic.h"
const int serPort = 2305;
const char* serIp = "192.168.10.104";
void upload_files(int);
int open_file();
void view_files(int,int);
void show_menu(int);
int main(int argc, const char *argv[])
{
int sfd;
struct sockaddr_in sin;
int len = sizeof(sin);
//create socket
create_socket(&sfd);
//turn the socket sfd into connected fd
connect_server(&sfd,&sin,len,serPort,serIp);
show_menu(sfd);
close(sfd);
return 0;
}
全部功能函数
#include "dic.h"
//show the content of a string(an array of char) element by element
void show_buffer(char *buf){
for(int i = 0;i < sizeof(buf); i++){
printf("%c",buf[i]);
}
printf(" at line %d.\n",__LINE__);
}
//to deal with dead child process
void zombie_deal(int signal){
while(waitpid(-1,NULL,WNOHANG) > 0);
}
//convert struct tm to string
void time_to_string(char* buf){
time_t t = time(NULL);
struct tm *tm = localtime(&t);
sprintf(buf,"%d-%02d-%02d %02d:%02d:%02d",tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec);
}
//the function is called by the server to tell the user if his request succeed or not
//every time when receiving a client request,such as register,log in,look up or view history
//for the attribute flag, normally 1 means success and 0 means fail.
void send_client_flag(int newfd,char* buf,int flag){
bzero(buf,sizeof(buf));
*(uint16_t*)buf = htons(flag);
if(send(newfd,buf,sizeof(buf),0) < 0){
ERR_MSG("Send flag");
exit(0);
}
SUC_MSG("Send flag");
}
//to open the databse at the beginning phase
void sql_open(const char* path,sqlite3** db){
if(sqlite3_open(path,db) < 0){
ERR_MSG("Open database");
exit(0);
}
SUC_MSG("Open database");
}
void sql_init_dictionary(sqlite3* db){
char* errMsg = 0;
int rc = 0;
char sql[128] = "";
//open the txt file which needs reading
FILE *fp;
char spell[128] = "";
char meaning[128] = "";
fp = fopen("dict.txt","r");
if(fp == NULL){
printf("Failed to open the txt file\n");
exit(0);
}
SUC_MSG("dict.txt open");
//store the max size of the txt file
fseek(fp,0,SEEK_END);
int totalByte = ftell(fp);
fseek(fp,0,SEEK_SET);
//while not reaching the end of the file,read every line and save the word
//into the table
while(1){
//the first string before the space will be the spell of a word
int j = 0;
while(1){
spell[j] = fgetc(fp);
// when meeting a space,break to read the next word
if(spell[j] == 32){
spell[j] = 0;
break;
}else if(spell[j] == EOF){
break;
}
j++;
}
int i = 0;
//the second string(might containing space) will be the meaning of a
//word
while(1){
meaning[i] = fgetc(fp);
// when meeting a \n,break to read the next word
if(meaning[i] == '\n'){
meaning[i] = 0;
break;
}else if(meaning[i] == EOF){
break;
}
if(meaning[i] != 32){
i++;
}
}
//if reaching the end of the file, break out of the loop
if(meaning[i] == EOF){
break;
}
//printf the current progress of reading && saving
long cur = ftell(fp);
float percentage = (cur / (float)totalByte) * 100;
if(cur < totalByte){
fprintf(stdout,"reading: %d%%\r",(int)percentage);
fflush(stdout);
}else{
fprintf(stdout,"reading: %d%%\n",(int)percentage);
}
//clear sql statement
bzero(sql,sizeof(sql));
//insert the word into the table
sprintf(sql,"insert into dictionary(spell, meaning) values(\"%s\",\"%s\");",spell,meaning);
rc = sqlite3_exec(db,sql,NULL,NULL,&errMsg);
if(rc != SQLITE_OK){
printf("Error insert: %s at %d \n",sqlite3_errmsg(db),__LINE__);
exit(0);
}
//clear both buffers
bzero(spell,sizeof(spell));
bzero(meaning,sizeof(meaning));
}
SUC_MSG("Record into table");
sqlite3_free(errMsg);
}
void sql_init_tables(sqlite3 *db){
char **pRes = NULL;
int row = 0;
int column = 0;
char sql[256] = "";
char* errMsg = 0;
int rc = 0;
// create the dictionary table if not exist
strcpy(sql,"CREATE TABLE IF NOT EXISTS DICTIONARY(ID INTEGER PRIMARY KEY AUTOINCREMENT, SPELL CHAR, MEANING CHAR);");
rc = sqlite3_exec(db,sql,NULL,NULL,&errMsg);
if(rc != SQLITE_OK){
printf("Error create table dictionary: %s at %d \n",sqlite3_errmsg(db), __LINE__);
exit(0);
}
SUC_MSG("Create table DICTIONARY");
// create the user table if not exist
strcpy(sql,"CREATE TABLE IF NOT EXISTS USER(ID INTEGER PRIMARY KEY AUTOINCREMENT, USERNAME CHAR, USERPASSWORD CHAR, FLAG INT);");
rc = sqlite3_exec(db,sql,NULL,NULL,&errMsg);
if(rc != SQLITE_OK){
printf("Error create table user: %s at %d \n",sqlite3_errmsg(db), __LINE__);
exit(0);
}
SUC_MSG("Create table USER");
// create the history table if not exist
strcpy(sql,"CREATE TABLE IF NOT EXISTS HISTORY(ID INTEGER PRIMARY KEY AUTOINCREMENT, USERNAME CHAR,SPELL CHAR, MEANING CHAR, TIME DATETIME);");
rc = sqlite3_exec(db,sql,NULL,NULL,&errMsg);
if(rc != SQLITE_OK){
printf("Error create table HISTORY: %s at %d \n",sqlite3_errmsg(db), __LINE__);
exit(0);
}
SUC_MSG("Create table HISTORY");
//check if it's the first time server boots
strcpy(sql,"SELECT * FROM DICTIONARY WHERE ID = 1;");
rc = sqlite3_get_table(db,sql,&pRes,&row,&column,&errMsg);
if(rc != SQLITE_OK){
printf("Error check if table empty: %s at %d \n",sqlite3_errmsg(db), __LINE__);
exit(0);
}
if(row == 0){
printf("This is the first time that server boots, start loading data from txt file\n");
sql_init_dictionary(db);
}
sqlite3_free(errMsg);
}
//the function is called by the server to re-set a specific user's flag back to 1
//when a user log out,whether its normally or interupted,
void sql_flag_back(sqlite3* db, char* username){
char sql[128] = "";
char *errMsg;
sprintf(sql,"UPDATE USER SET FLAG = 1 WHERE USERNAME = \"%s\";",username);
int rc = sqlite3_exec(db,sql,NULL,NULL,&errMsg);
if(rc != SQLITE_OK){
printf("Error flag back touser table: %s at %d \n",sqlite3_errmsg(db), __LINE__);
exit(0);
}
sqlite3_free(errMsg);
SUC_MSG("User flag reset");
}
//the function will be called after a user finished look up request.
void insert_history(sqlite3* db,char* username,char* word, char* meaning, char* curtime){
char **pRes = NULL;
int row = 0;
int column = 0;
char sql[128] = "";
char* errMsg = 0;
int rc = 0;
//check if there is duplicated searching record of the specific user on the same word
sprintf(sql,"SELECT * FROM HISTORY WHERE USERNAME = \"%s\" AND SPELL = \"%s\";",username,word);
rc = sqlite3_get_table(db,sql,&pRes,&row,&column,&errMsg);
if(rc != SQLITE_OK){
printf("Error search from history: %s at %d \n",sqlite3_errmsg(db), __LINE__);
exit(0);
}
SUC_MSG("Search from history");
// if there isn't any record about this user searching on this word,insert
// new record
if(row == 0){
sprintf(sql,"INSERT INTO HISTORY(USERNAME, SPELL, MEANING, TIME) VALUES(\"%s\", \"%s\", \"%s\", \"%s\");",username,word,meaning,curtime);
int rc = sqlite3_exec(db,sql,NULL,NULL,&errMsg);
if(rc != SQLITE_OK){
printf("Error insert record into history: %s at %d \n",sqlite3_errmsg(db), __LINE__);
exit(0);
}
SUC_MSG("Insert into history");
//if there has been already a record,update the time column, modify it with
//the latest time.
}else{
sprintf(sql,"UPDATE HISTORY SET TIME = \"%s\" WHERE USERNAME = \"%s\" AND SPELL = \"%s\";",curtime,username,word);
int rc = sqlite3_exec(db,sql,NULL,NULL,&errMsg);
if(rc != SQLITE_OK){
printf("Error update record into history: %s at %d \n",sqlite3_errmsg(db), __LINE__);
exit(0);
}
SUC_MSG("Update history");
}
sqlite3_free(errMsg);
sqlite3_free_table(pRes);
}
//this function is called after receiving a request with an look up request
//operation code
void sql_look_up(int newfd, sqlite3* db,char* buf,char* username){
int rc = 0;
int row = 0;
int column = 0;
char **pRes = NULL;
char *errMsg = NULL;
char sql[128] = "";
char word[128] = "";
char curtime[32] = "";
//extract the word from the buffer
sprintf(word,"%s",buf+sizeof(short));
strcpy(username,buf+ sizeof(short) + strlen(word)+1);
printf("word = %s username = %s\n",word, username);
sprintf(sql,"SELECT * FROM DICTIONARY WHERE SPELL = \"%s\";",word);
rc = sqlite3_get_table(db,sql,&pRes,&row,&column,&errMsg);
if(rc != SQLITE_OK){
printf("Error check if user exists: %s at %d \n",sqlite3_errmsg(db), __LINE__);
exit(0);
}
//if the word doesn't exist,send back a flag
if(row == 0){
send_client_flag(newfd,buf,0);
}
//if the word exist,send back a flag along with the meaning
//save this search record to the database
else{
//send back to inform the user that the word is in the dictionary
bzero(buf,sizeof(buf));
*(short*)buf = htons(row);
if(send(newfd,buf,sizeof(buf),0) < 0){
ERR_MSG("Send back number of meaning");
}
SUC_MSG("Send back number of meaning");
char meaning[128] = "";
char buffer[256] = "";
for(int i = column; i < (row + 1) * column; i++){
if(i % column == column - 1){
//send back the meaning and at the same time
//prepare the meaning to save into history table
bzero(buffer,sizeof(buffer));
strcpy(buffer,pRes[i]);
SUC_MSG(pRes[i]);
buffer[strlen(pRes[i]) + 1] = '\0';
SUC_MSG(buffer);
if(send(newfd,buffer,sizeof(buffer),0) < 0){
ERR_MSG("Send back meaning");
}
strcat(meaning,pRes[i]);
}
}
time_to_string(curtime);
insert_history(db,username,word,meaning,curtime);
}
sqlite3_free(errMsg);
sqlite3_free_table(pRes);
}
//the function is called by the server after receiving a view history request
//from the client
void sql_view_history(int newfd, sqlite3* db,char* username){
int rc = 0;
int row = 0;
int column = 0;
char **pRes = NULL;
char *errMsg = NULL;
char sql[128] = "";
char buf[512] = "";
sprintf(sql,"SELECT * FROM HISTORY WHERE USERNAME = \"%s\" ORDER BY TIME DESC;",username);
rc = sqlite3_get_table(db,sql,&pRes,&row,&column,&errMsg);
if(rc != SQLITE_OK){
printf("Error check user history: %s at %d \n",sqlite3_errmsg(db), __LINE__);
exit(0);
}
SUC_MSG("View history");
//if there is no search record,send back a fail flag
if(row == 0){
send_client_flag(newfd,buf,0);
}
else{
//send string by string from **pRes
//send first how many strings there are to send
*(short*)buf = htons(row * (column -2));
*(short*)(buf+sizeof(short)) = htons(column);
if(send(newfd,buf,sizeof(buf),0) < 0){
ERR_MSG("Send record number");
}
SUC_MSG("Send record number");
//send back every element of *qRes except the column id and the column
//username
for(int i = column; i < (row + 1)*column;i++){
if((i % column != 0) && (i % column != 1)){
bzero(buf,sizeof(buf));
strcpy(buf,pRes[i]);
buf[strlen(pRes[i]) + 1] = '\0';
if(send(newfd,buf,sizeof(buf),0) < 0){
ERR_MSG("Send segments");
}
}
}
}
sqlite3_free_table(pRes);
sqlite3_free(errMsg);
}
int sql_if_user_exists(char* buf, char* username, char* userpassword,char* sql,sqlite3* db){
int rc = 0;
int row = 0;
int column = 0;
char **pRes = NULL;
char *errMsg = NULL;
sprintf(username,"%s",buf+sizeof(short));
sprintf(userpassword,"%s",buf+sizeof(short)+strlen(username)+sizeof(char));
sprintf(sql,"SELECT * FROM USER WHERE USERNAME = \"%s\";",username);
rc = sqlite3_get_table(db,sql,&pRes,&row,&column,&errMsg);
if(rc != SQLITE_OK){
printf("Error check if user exists: %s at %d \n",sqlite3_errmsg(db), __LINE__);
exit(0);
}
if(row == 0){
sqlite3_free_table(pRes);
sqlite3_free(errMsg);
return 0;
}
else{
sqlite3_free_table(pRes);
sqlite3_free(errMsg);
return 1;
}
sqlite3_free_table(pRes);
sqlite3_free(errMsg);
return 0;
}
void sql_register_user(char* sql, char* username,char* userpassword, sqlite3* db){
char *errMsg;
sprintf(sql,"INSERT INTO USER(USERNAME, USERPASSWORD, FLAG) VALUES(\"%s\", \"%s\", 1);",username,userpassword);
int rc = sqlite3_exec(db,sql,NULL,NULL,&errMsg);
if(rc != SQLITE_OK){
printf("Error insert into user table: %s at %d \n",sqlite3_errmsg(db), __LINE__);
exit(0);
}
sqlite3_free(errMsg);
SUC_MSG("One record inserted");
}
int sql_login_user(int newfd, char* buf, char* username,char* userpassword,char* sql, sqlite3* db){
int row = 0;
int column = 0;
char **pRes = NULL;
char *errMsg = NULL;
int rc = sql_if_user_exists(buf,username,userpassword,sql,db);
//if a user doesn't exists send back a failure flag
if(rc == 0){
send_client_flag(newfd,buf,0);
//if exist,check if the password matches
}else{
sprintf(username,"%s",buf+sizeof(short));
sprintf(userpassword,"%s",buf+sizeof(short)+strlen(username)+sizeof(char));
sprintf(sql,"SELECT * FROM USER WHERE USERNAME = \"%s\" AND USERPASSWORD = \"%s\" AND FLAG = 1;",username,userpassword);
rc = sqlite3_get_table(db,sql,&pRes,&row,&column,&errMsg);
if(rc != SQLITE_OK){
printf("Error check if user exists: %s at %d \n",sqlite3_errmsg(db), __LINE__);
exit(0);
}
//if doesn't match,send back a failure flag
if(row == 0){
send_client_flag(newfd,buf,0);
sqlite3_free(errMsg);
return 0;
}
//if do exist,send back a success flag as well as modify the user record
//to re-set the flag column to 0
else{
send_client_flag(newfd,buf,1);
sprintf(sql,"UPDATE USER SET FLAG = 0 WHERE USERNAME = \"%s\";",username);
rc = sqlite3_exec(db,sql,NULL,NULL,&errMsg);
if(rc != SQLITE_OK){
printf("Error insert into user table: %s at %d \n",sqlite3_errmsg(db), __LINE__);
exit(0);
}
SUC_MSG("User log in");
sqlite3_free(errMsg);
return 1;
}
}
sqlite3_free(errMsg);
return 0;
}
//reset all the users' flag to 1 after rebooting the server
void sql_reset_all_flags(sqlite3* db){
char *errMsg = 0;
char sql[128] = "UPDATE USER SET FLAG = 1";
int rc = sqlite3_exec(db,sql,NULL,NULL,&errMsg);
if(rc != SQLITE_OK){
printf("Error reset flags: %s at %d \n",sqlite3_errmsg(db), __LINE__);
exit(0);
}
SUC_MSG("Reset all users' flag");
}
void create_socket(int *sfd){
*sfd = socket(AF_INET,SOCK_STREAM,0);
if(sfd < 0){
ERR_MSG("Create socket");
exit(0);
}
SUC_MSG("Socket");
}
void bind_socket(int *sfd,struct sockaddr_in *sin, int *len, int port, const char* ip){
sin->sin_family = AF_INET;
sin->sin_port = htons(port);
sin->sin_addr.s_addr = inet_addr(ip);
if(bind(*sfd,(struct sockaddr*)sin,*len) < 0){
ERR_MSG("Bind socket");
exit(0);
}
SUC_MSG("Bind");
}
void quick_reuse(int *sfd){
int reuse = 1;
if(setsockopt(*sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)) < 0){
ERR_MSG("Reuse port");
}
SUC_MSG("Reuse port");
}
void listen_socket(int *sfd){
if(listen(*sfd,128) < 0){
ERR_MSG("Listen socket");
exit(0);
}
SUC_MSG("Listen");
}
void connect_server(int *sfd,struct sockaddr_in *sin, socklen_t addrlen,int port, const char* ip){
sin->sin_family = AF_INET;
sin->sin_port = htons(port);
sin->sin_addr.s_addr = inet_addr(ip);
if(connect(*sfd,(struct sockaddr*)sin,addrlen) < 0){
ERR_MSG("Connect server");
exit(0);
}
SUC_MSG("Connected to server");
}
int accept_socket(int sfd,struct sockaddr_in *addr, socklen_t *addrlen){
int newfd;
newfd = accept(sfd,(struct sockaddr*)addr,addrlen);
if(newfd < 0){
ERR_MSG("Accept socket");
return -1;
}
printf("[%s:%d] has successfully connected at line %d\n",inet_ntoa(addr->sin_addr),ntohs(addr->sin_port),__LINE__);
return newfd;
}
void deal_dictionary(int newfd,struct sockaddr_in cin,sqlite3* db,char* username){
char buf[256] = "";
//look up or view history
while(1){
bzero(buf,sizeof(buf));
int res = recv(newfd,buf,sizeof(buf),0);
if(res <= 0){
//update the user table and change the flag to 1
printf("[%s:%d] has been off at line %d\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),__LINE__);
if(close(newfd) < 0){
ERR_MSG("Close");
}
sql_flag_back(db, username);
exit(0);
}
SUC_MSG("Request from user");
if(ntohs(*(short*)buf) == 3){
sql_look_up(newfd,db,buf,username);
}else if(ntohs(*(short*)buf) == 4){
sql_view_history(newfd,db,username);
}else if(ntohs(*(short*)buf) == 5){
sql_flag_back(db, username);
printf("[%s:%d] has logged out at line %d\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),__LINE__);
break;
}
}
}
void deal_client(int newfd,struct sockaddr_in cin,sqlite3* db){
//operation code(client to server):
//the first 2 bytes of string will be the operation code
//1.register strlen(username) + 0 1byte + strlen(userpassword) + 0 1byte
//2.login + strlen(username) +0 1byte + strlen(userpassword) + 0 1byte
//3.look up strlen(spell) + 0 1byte
//4.view history
//5.quit second menu
//operation code(server to client):
//1 means success
//0 means failure
//>1 means in view history means number of records
//log in or register
char buf[256] = "";
char sql[128] = "";
char username[16] = "";
char userpassword[16] = "";
while(1){
bzero(buf,sizeof(buf));
int res = recv(newfd,buf,sizeof(buf),0);
SUC_MSG("Receive from cli");
if(res <= 0){
//user quit without log in
printf("[%s:%d] has been off at line %d\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),__LINE__);
if(close(newfd) < 0){
ERR_MSG("Close");
}
exit(0);
}
if(ntohs(*(short*)buf) == 1){
//if successfully registered
//insert its name and password into the user table
int rc = sql_if_user_exists(buf,username,userpassword,sql,db);
if(rc == 0){
sql_register_user(sql,username,userpassword,db);
send_client_flag(newfd,buf,1);
}else{
send_client_flag(newfd,buf,0);
}
}else if(ntohs(*(short*)buf) == 2){
//if successfully log in
//update the user table and alter the flag to 0
if(sql_login_user(newfd,buf,username,userpassword,sql,db) == 1){
deal_dictionary(newfd,cin,db,username);
}
}
}
}
//called by the client if require looking up
void look_up(int sfd, char* username){
char word[32] = "";
char buf[256] = "";
char meaning[64] = "";
printf("please enter a word>>>");
fgets(word,sizeof(word),stdin);
word[strlen(word) - 1] = 0;
//Loop in case there are bad tcp requests
while(1){
bzero(buf,sizeof(buf));
sprintf(buf,"%c%c%s%c%s%c",0,3,word,'\0',username,'\0');
//send a look up request to the server
if(send(sfd,buf,sizeof(buf),0) < 0){
ERR_MSG("Send to server");
}
SUC_MSG("Send to server");
//receive the request result
bzero(buf,sizeof(buf));
ssize_t res = 0;
if((res=recv(sfd,buf,sizeof(buf),0)) < 0){
ERR_MSG("Look up");
}
printf("res=%ld __%d__\n", res, __LINE__);
SUC_MSG("Look up");
//if the word exists in the dictionary
if(ntohs(*(short*)buf) >= 1){
SUC_MSG("The word found");
int num = ntohs(*(short*)buf);
for(int i = 0; i < num;i++){
bzero(buf,sizeof(buf));
if(recv(sfd,buf,sizeof(buf),0) < 0){
ERR_MSG("Look up");
}
SUC_MSG(buf);
strcat(meaning,buf);
if(strcmp(meaning,"") == 0){
fflush(stdout);
}
}
if(strcmp(meaning,"") != 0){
printf("The word means %s,\n",meaning);
break;
}
}else{
printf("The word isn't included in the dictionary.\n");
break;
}
}
}
//called by the client if require viewing history
void view_history(int sfd,char* username){
char buf[512] = "";
sprintf(buf,"%c%c%s%c",0,4,username,'\0');
//send a view request to the server
if(send(sfd,buf,sizeof(buf),0) < 0){
ERR_MSG("Send to server");
}
SUC_MSG("Send to server");
//receive the request result
bzero(buf,sizeof(buf));
if(recv(sfd,buf,sizeof(buf),0) < 0){
ERR_MSG("View history");
}
SUC_MSG("View history");
if(ntohs(*(short*)buf) == 0){
printf("No record of user %s.\n",username);
return;
}
else{
//print out every string from the server
//print out \n every 3 strings
int num = ntohs(*(short*)buf);
int column = ntohs(*(short*)(buf + sizeof(short)));
for(int i = 0; i < num; i++){
bzero(buf,sizeof(buf));
if(recv(sfd,buf,sizeof(buf),0) < 0){
ERR_MSG("View history");
}
printf("%-15s ",buf);
if((i % (column - 2)) == (column - 3)){
puts("");
}
}
}
puts("");
}
void log_out(int sfd){
char buf[2];
*(uint16_t *)buf = htons(5);
if(send(sfd,buf,sizeof(buf),0) < 0){
ERR_MSG("Send log out");
}
SUC_MSG("Log out");
}
void show_second_menu(int sfd, char* username){
char buf[256]="";
ssize_t res = 0;
// if((res=recv(sfd,buf,sizeof(buf),0)) < 0){
// ERR_MSG("Look up");
// }
printf("res=%ld __%d__\n", res, __LINE__);
char c;
while(1){
printf("_________Welcome________\n");
printf(" %s\n",username);
printf("------------------------\n");
printf("| 1.look up |\n");
printf("| 2.view history |\n");
printf("| 3.exit |\n");
printf("------------------------\n");
c = getchar();
system("clear");
while(getchar()!= 10);
if( c == '1'){
look_up(sfd,username);
}else if(c == '2'){
view_history(sfd,username);
}else if(c == '3'){
log_out(sfd);
break;
}else{
printf("Not a valid option,please re-enter\n");
}
}
}
void cli_register(int sfd){
char username[16] = "";
char password[16] = "";
//operation code 2bytes + username + \0 + password + \0
char buf[36] = "";
printf("| 1.register |\n");
printf("username>>>");
fgets(username,sizeof(username),stdin);
username[strlen(username) - 1] = 0;
printf("password>>>");
fgets(password,sizeof(password),stdin);
password[strlen(password) - 1] = 0;
sprintf(buf,"%c%c%s%c%s%c",0,1,username,'\0',password,'\0');
//send the register info to the server
if(send(sfd,buf,sizeof(buf),0) < 0){
ERR_MSG("Send to server");
}
SUC_MSG("Send to server");
//collect the success flag from the server
bzero(buf,sizeof(buf));
if(recv(sfd,buf,sizeof(buf),0) < 0){
ERR_MSG("Receive from server");
}
SUC_MSG("Flag received");
if(ntohs(*(short*)buf) == 1){
printf("User %s is successfully registered.\n",username);
}else{
printf("User %s has already been registered.\n",username);
}
}
void cli_log_in(int sfd){
char username[16] = "";
char password[16] = "";
//operation code 2bytes + strlen(username) + \0 + strlen(password) + \0
char buf[36] = "";
printf("| 2.log in |\n");
printf("username>>>");
fgets(username,sizeof(username),stdin);
username[strlen(username) - 1] = 0;
printf("password>>>");
fgets(password,sizeof(password),stdin);
password[strlen(password) - 1] = 0;
sprintf(buf,"%c%c%s%c%s%c",0,2,username,'\0',password,'\0');
//send the register info to the server
if(send(sfd,buf,sizeof(buf),0) < 0){
ERR_MSG("Send to server");
}
SUC_MSG("Send to server");
//collect the success flag from the server
bzero(buf,sizeof(buf));
if(recv(sfd,buf,sizeof(buf),0) < 0){
ERR_MSG("Receive from server");
}
SUC_MSG("Flag received");
if(ntohs(*(short*)buf) == 1){
printf("User %s has successfully logged in.\n",username);
show_second_menu(sfd,username);
}else{
printf("User %s log in failed.\n",username);
}
}
void show_first_menu(int sfd){
char c;
while(1){
printf("_______E-dictionary_____\n");
printf("------------------------\n");
printf("| 1.register |\n");
printf("| 2.log in |\n");
printf("| 3.exit |\n");
printf("------------------------\n");
c = getchar();
system("clear");
while(getchar()!= 10);
if( c == '1'){
cli_register(sfd);
}else if(c == '2'){
cli_log_in(sfd);
}else if(c == '3'){
break;
}else{
printf("Not a valid option,please re-enter\n");
}
}
}