client.c
#include<stdio.h>
#include<string.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<linux/in.h>
#include<stdlib.h>//消息数据包
typedef struct msg
{
int type;//类型
char name[128];//用户名
char data[256];//内容
}MSG;
void do_register(int sockfd,MSG *msg);
int do_login(int sockfd,MSG *msg);
void do_query(int sockfd,MSG *msg);
void do_history(int sockfd,MSG *msg);
int main(int argc, const char *argv[])
{
if(argc < 3)
{
printf("input : %s<ip> <port>\n",argv[0]);
exit(0);
}
MSG msg;
int login = 0;
//创建套节字文件
int sockfd;
if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0)
{
perror("sockfd err.\n");
return -1;
}
printf("socket yes.\n");
//填充结构体数组
struct sockaddr_in serveraddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(atoi(argv[2]));
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);//允许重用本地地址 和端口号
int optval = 1;
socklen_t optval_len = sizeof(optval);
setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&optval,optval_len);socklen_t addrlen = sizeof(serveraddr);
//连接服务器
if(connect(sockfd,(struct sockaddr *)&serveraddr,addrlen) < 0)
{
perror("connect err.\n");
return -1;
}
printf("connect yes\n");
char buf[128] = {0};
int n = 0;
while(1)
{ //注册.登录.退出
printf("*******************************\n");
printf("* 1:register 2:login 3:quit *\n");
printf("*******************************\n");
printf("please choose>>>");
if(scanf("%d",&n) == 0)
{
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf) -1] = '\0';
continue;
}
switch(n)
{
case 1:
do_register(sockfd,&msg);
break;
case 2:
if(do_login(sockfd,&msg) == 1)
{
goto next;
}
break;
case 3:
close(sockfd);
exit(0);
}
}void do_register(int sockfd,MSG *msg)
{
//封装注册msg包
msg->type = 'R';
printf("please user name:");
scanf("%s",msg->name);
printf("please user code:");
scanf("%s",msg->data);
//向服务器发送注册包
send(sockfd,msg,sizeof(MSG),0);
//接收服务器反馈
recv(sockfd,msg,sizeof(MSG),0);
printf("register: %s\n",msg->data);
return;
}
int do_login(int sockfd,MSG *msg)
{
//封装登录包
msg->type = 'L';
printf("please user name:");
scanf("%s",msg->name);
printf("please user code:");
scanf("%s",msg->data);
//发送登录消息
send(sockfd,msg,sizeof(MSG),0);
//接收服务器反馈
recv(sockfd,msg,sizeof(MSG),0);
//判断是否登录成功
if(strncmp(msg->data,"OK",3) == 0)
{
printf("login OK.\n");
return 1;
}
printf("login:%s\n",msg->data);
return 0;
}
void do_query(int sockfd,MSG *msg)
{ //封装查询包
msg->type = 'Q';
while(1)
{
printf("query word:");
scanf("%s",msg->data);
if(strcmp(msg->data,"#") == 0)
break;
//发送查询信号
send(sockfd,msg,sizeof(MSG),0);
//接收服务器反馈
recv(sockfd,msg,sizeof(MSG),0);
//printf优化解释,打印
printf("%s\n",msg->data);}
return ;
}
void do_history(int sockfd,MSG *msg)
{
//封装历史查询包
msg->type = 'H';
send(sockfd,msg,sizeof(MSG),0);
while(1)
{
recv(sockfd,msg,sizeof(MSG),0);
if( msg->data[0] == '\0')
break;
printf("%s\n",msg->data);
}
return;
}
Makefile
all:
gcc server.c -lsqlite3 -o fwq
gcc client.c -o khdclean:
rm fwq khd
Sever.c
#include<stdio.h>
#include<sqlite3.h>
#include<string.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<sys/socket.h>//消息数据包
typedef struct
{
int type;//类型
char name[128];//用户名
char data[256];//内容
}MSG;
int callback(void *arg,int f_num,char **f_value,char **f_name);
void get_date(char *date);
int do_searchword(int acceptfd, MSG *msg);
void do_register(int acceptfd,MSG *msg,sqlite3 *db);
void do_login(int acceptfd,MSG *msg,sqlite3 *db);
void do_query(int acceptfd,MSG *msg,sqlite3 *db);
void do_history(int acceptfd,MSG *msg,sqlite3 *db);
int main(int argc, const char *argv[])
{
if(argc < 3)
{
printf("input :%s,<ip> <port>\n",argv[0]);
exit(0);
}
sqlite3 *db;
char *errmsg = NULL;
int sockfd,acceptfd;
ssize_t recvaddr;
MSG msg;
char buf[128] = {0};
//创建一个数据库文件
if(sqlite3_open("str.db",&db) != 0)
{
fprintf(stderr,"sqlite3_open failed:%s\n",sqlite3_errmsg(db));
return -1;
}
printf("open yes.\n");
//添加一个用户信息表,key表明注册的用户名只能唯一
if(sqlite3_exec(db,"create table str(name char primary key,code char);",NULL,NULL,&errmsg) != 0)
{
fprintf(stderr,"create str failed:%s\n",errmsg);
}
printf("exec yes.\n");
//添加一个历史记录的表
if(sqlite3_exec(db,"create table record(name char,time char,word char);",NULL,NULL,&errmsg) != 0)
{
fprintf(stderr,"create record failed:%s\n",errmsg);
}
//创建一个套节字文件
if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0)
{
perror("socket err.\n");
return -1;
}
printf("socket yes.\n");
//填充结构体数组
struct sockaddr_in serveraddr,clinentaddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(atoi(argv[2]));
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);//允许重用本地地址 和端口号
int optval = 1;
socklen_t optval_len = sizeof(optval);
setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&optval,optval_len);socklen_t serverlen = sizeof(serveraddr);
socklen_t clinentlen = sizeof(clinentaddr);
//绑定
if(bind(sockfd,(struct sockaddr *)&serveraddr,serverlen) < 0)
{
perror("bind err.\n");
return -1;
}
printf("bind yes.\n");
//监听
if(listen(sockfd,8) < 0)
{
perror("listen err.\n");
return -1;
}
printf("listen yes.\n");//信号处理函数
signal(SIGCHLD,SIG_IGN);pid_t pid;
while(1)
{ //阻塞等待连接
if((acceptfd = accept(sockfd,NULL,NULL)) < 0)
{
perror("acceptfd err.\n");
return -1;
}
printf("accept yes.\n");
//创建进程
if((pid = fork()) < 0)
{
perror("fork err.\n");
return -1;
}
else if(pid == 0)
{
//循环接收客户端数据存放到msg包里
while(recvaddr = recv(acceptfd,&msg,sizeof(msg),0) > 0)
{
//根据类型处理
switch(msg.type)
{
case 'R'://.注册
do_register(acceptfd,&msg,db);
break;
case 'L'://.登录
do_login(acceptfd,&msg,db);
break;
case 'Q'://.查询的单词
do_query(acceptfd,&msg,db);
break;
case 'H'://.历史记录
do_history(acceptfd,&msg,db);
break;
}
}
printf("ip%sclient quit!!!!\n",(char *)inet_ntoa(clinentaddr.sin_addr.s_addr));
close(acceptfd);
exit(0);
}
else
{
printf("** user login. **\n");
}
}
close(sockfd);
return 0;
}
完整代码请参考: https://download.youkuaiyun.com/download/signal___/18161310?spm=1001.2014.3001.5501
TCP/IP通信的客户端实现及服务器响应处理

这是一个C语言实现的TCP/IP通信客户端和服务器的代码示例。客户端可以进行注册、登录、查询和查看历史记录的操作,服务器端处理这些请求并与数据库交互。代码中包含了SQLite数据库操作,用于存储用户信息和历史记录。
2070





