//单词导入数据库
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sqlite3.h>
#include <fcntl.h>
int do_insert(sqlite3 *db);
int main(int argc, const char *argv[])
{
if(argc<2){
printf("输入错误请重新输入\n");
return -1;
}
sqlite3 *db1=NULL;
if(sqlite3_open(argv[1],&db1)!=SQLITE_OK){
fprintf(stderr,"sqlite3_open:%s errcode:%d __%d__\n",sqlite3_errmsg(db1),sqlite3_errcode(db1),__LINE__);
return -1;
}
//创建表格
char buf[128]="create table if not exists dict (English char, Chinese char);";
char *errmsg=NULL;
if(sqlite3_exec(db1,buf,NULL,NULL,&errmsg)!=SQLITE_OK){
fprintf(stderr,"sqlites_exec:%s __%d__\n",errmsg,__LINE__);
return -1;
}
do_insert(db1);
//关闭表格
if(sqlite3_close(db1)!=SQLITE_OK){
fprintf(stderr,"sqlite3_close:%s errcode:%d __%d__\n",\
sqlite3_errmsg(db1),sqlite3_errcode(db1),__LINE__);
return -1;
}
return 0;
}
/*
* function: 增
* @param [ in] 单词文本行数,数据库首地址
* @param [out]
* @return 成功返回0,失败返回-1;
*/
int do_insert(sqlite3 *db){
FILE *fd=fopen("dict.txt","r+");
if(NULL==fd){
perror("fopen fd");
return -1;
}
int id;
char english[128]="";
char chinese[128]="";
char buf[128]="";
char str[520]="";
int j=0;
char *errmsg=NULL;
while(1){
bzero(buf,sizeof(buf));
bzero(str,sizeof(str));
bzero(english,sizeof(english));
bzero(chinese,sizeof(chinese));
fgets(buf,sizeof(buf),fd);
buf[strlen(buf)-1]=0;
if(strlen(buf)==0){
break;
}
for(j=0;j<strlen(buf)-2;j++){
if(buf[j]!=' '&&buf[j+1]==' '&&buf[j+2]==' ')
{
strncpy(english,buf,j+1);
}
else if(buf[j]==' '&&buf[j+1]==' '&&buf[j+2]!=' ')
{
strcpy(chinese,buf+j+2);
}
}
sprintf(str,"insert into dict values (\"%s\",\"%s\");",english,chinese);
if(sqlite3_exec(db,str,NULL,NULL,&errmsg)!=SQLITE_OK){
fprintf(stderr,"sqlite3_exec:%s __%d__\n",errmsg,__LINE__);
}
id++;
}
fclose(fd);
return 0;
}
UDP网络聊天室
//服务器端
//通过老师的代码改善
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
//定义链表信息
typedef struct Node{
//存储接收的客户端的信息
struct sockaddr_in cin;
//定义链表指针域
struct Node *next;
}*LinkList;
//协议
#define LOGIN 1
#define CHAT 2
#define QUIT 3
//收发信息的结构体
typedef struct
{
int type;
char name[20];
char text[128];
}MSG;
#define PRINT_ERR(msg) do{\
fprintf(stderr,"failed __%d__\n",__LINE__);\
perror(msg);\
}while(0)
#define PORT 6666
#define IP "192.168.1.5"
LinkList my_malloc_head();
int do_recv(int sfd, LinkList link);
int do_login(int sfd, LinkList link, MSG rcv_msg, struct sockaddr_in cin);
int do_quit(int sfd, LinkList link, MSG rcv_msg, struct sockaddr_in cin);
int do_chat(int sfd, LinkList list, MSG rcv_msg, struct sockaddr_in cin);
int do_system(int sfd, struct sockaddr_in sin);
int main(int argc, const char *argv[])
{
//创建套接字
int sfd=socket(AF_INET,SOCK_DGRAM,0);
if(sfd<0){
PRINT_ERR("socket");
return -1;
}
//绑定服务器IP和端口号
struct sockaddr_in sin;
sin.sin_family=AF_INET;
sin.sin_port=htons(PORT);
sin.sin_addr.s_addr=inet_addr(IP);
if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))<0){
PRINT_ERR("bind");
return -1;
}
pid_t pid=fork();
if(pid>0){
//父进程,接收信息
//创建头结点
LinkList link=my_malloc_head();
do_recv(sfd,link);
}else if(0==pid){
//子进程,发送系统消息
do_system(sfd,sin);
}
//关闭套接字
close(sfd);
return 0;
}
/*
* function: 在堆区为链表头结点申请内存空间
* @param [ in] 无参数
* @param [out]
* @return 成功返回头结点申请到的堆区地址,失败返回NULL
*/
LinkList my_malloc_head(){
LinkList link=(LinkList)malloc(sizeof(struct Node));//LinkList代表结构体指针类型,sizeof里面不能写LinkList,要写结构体名struct Node
if(link==NULL){
return NULL;
}else{
link->next=NULL;
return link;
}
}
/*
* function: 发送系统消息
* @param [ in] 套接字,服务器信息
* @param [out]
* @return 成功返回0,失败返回-1;
*/
int do_system(int sfd, struct sockaddr_in sin)
{
MSG sys_msg = {htonl(CHAT), "**system**"};
while(1){
bzero(sys_msg.text, sizeof(sys_msg.text));
fgets(sys_msg.text, sizeof(sys_msg.text), stdin);
sys_msg.text[strlen(sys_msg.text)-1] = 0;
//将当前进程当做客户端,父进程当做服务器,发送信息;
if(sendto(sfd, &sys_msg, sizeof(sys_msg), 0, (void*)&sin, sizeof(sin)) < 0){
PRINT_ERR("sendto");
return -1;
}
}
printf("系统消息发送成功");
return 0;
}
/*
* function: 接收信息
* @param [ in] 套接字,链表头结点
* @param [out]
* @return 成功返回0,失败返回-1;
*/
int do_recv(int sfd,LinkList link)
{
MSG rcv_msg;
int recv_len = 0;
struct sockaddr_in cin;
socklen_t addrlen = sizeof(cin);
while(1){
//接收消息
recv_len = recvfrom(sfd, &rcv_msg, sizeof(rcv_msg), 0, (void*)&cin, &addrlen);
if(recv_len < 0){
PRINT_ERR("recvfrom");
return -1;
}
//提取出协议
//将网络字节序转换为主机字节序
int type = ntohl(rcv_msg.type);
switch(type){
case LOGIN:
do_login(sfd, link, rcv_msg, cin);
break;
case CHAT:
do_chat(sfd, link, rcv_msg, cin);
break;
case QUIT:
do_quit(sfd, link, rcv_msg, cin);
break;
}
}
}
/*
* function: 聊天协议
* @param [ in] 套接字,链表头结点,客户端信息
* @param [out]
* @return 成功返回0,失败返回-1;
*/
int do_chat(int sfd,LinkList link, MSG rcv_msg, struct sockaddr_in cin){
printf("%s [%s:%d]chat成功\n", rcv_msg.name,\
(char*)inet_ntoa(cin.sin_addr), ntohs(cin.sin_port));
//重新拼接群聊消息: 名字+消息
char buf[258] = "";
sprintf(buf, "%s:%s", rcv_msg.name, rcv_msg.text);
strcpy(rcv_msg.text, buf);
//循环发送,除了自己以外的ip地址
while(link->next != NULL){
link = link->next;
if(memcmp(&cin, &link->cin, sizeof(cin)) != 0){
if(sendto(sfd, &rcv_msg, sizeof(rcv_msg),0, (void*)&(link->cin), sizeof(link->cin))<0){
PRINT_ERR("sendto");
return -1;
}
}
}
return 0;
}
/*
* function: 客户端下线
* @param [ in] 套接字,链表头结点,接收信息,客户端信息
* @param [out]
* @return 成功返回0,失败返回-1;
*/
int do_quit(int sfd,LinkList link, MSG rcv_msg, struct sockaddr_in cin){
sprintf(rcv_msg.text, "-----%s 已下线-----\n", rcv_msg.name);
//循环遍历链表,发送客户端下线的信息
//发送给当前客户端外的其余客户端
while(link->next != NULL){
if(memcmp(&cin, &link->next->cin, sizeof(cin)) == 0){
//从链表中删除该客户端信息
//free
LinkList temp = link->next;
link->next = temp->next;
free(temp);
}
else{
link = link->next;
if(sendto(sfd, &rcv_msg, sizeof(rcv_msg),0, (void*)&link->cin, sizeof(link->cin))<0){
PRINT_ERR("sendto");
return -1;
}
}
}
return 0;
}
/*
* function: 客户端登录
* @param [ in] 套接字,链表头结点,接收信息,客户端信息
* @param [out]
* @return 成功返回0,失败返回-1;
*/
int do_login(int sfd, LinkList link, MSG rcv_msg, struct sockaddr_in cin){
//打印登录成功
printf("%s [%s:%d]登录成功\n", rcv_msg.name,\
(char*)inet_ntoa(cin.sin_addr), ntohs(cin.sin_port));
sprintf(rcv_msg.text, "-----%s登录成功-----", rcv_msg.name);
while(link->next != NULL){
link = link->next;
if(sendto(sfd, &rcv_msg, sizeof(rcv_msg), 0, (void*)&(link->cin), sizeof(link->cin))<0){
PRINT_ERR("sendto");
return -1;
}
}
//将登录成功的客户端信息添加到链表中;
LinkList temp = (LinkList)malloc(sizeof(struct Node));
temp->cin = cin;
temp->next= NULL;
link->next = temp;
return 0;
}
//客户端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <unistd.h>
#define PORT 6666
#define IP "192.168.1.5"
//协议
#define LOGIN 1
#define CHAT 2
#define QUIT 3
#define PRINT_ERR(msg) do{\
fprintf(stderr,"failed __%d__\n", __LINE__);\
perror(msg);\
}while(0)
//收发信息的结构体
typedef struct
{
int type;
char name[20];
char text[128];
}MSG;
typedef void (*sighandler_t)(int);
int do_recv(int cfd);
int do_chat(int cfd, MSG msg, struct sockaddr_in sin);
void handler(int sig){
//回收子进程资源并退出
while(waitpid(-1,NULL, WNOHANG)>0);
exit(0);
}
int main(int argc, const char *argv[])
{
//注册信号处理函数,让子进程退出后,父进程回收子进程资源并退出
sighandler_t s = signal(SIGCHLD, handler);
if(s == SIG_ERR){
PRINT_ERR("signal");
return -1;
}
//创建报式套接字
int cfd = socket(AF_INET, SOCK_DGRAM, 0);
if(cfd < 0){
PRINT_ERR("socket");
return -1;
}
//填充服务器ip和端口号
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(IP);
socklen_t addrlen = sizeof(sin);
//登录协议
MSG msg ;
msg.type = htonl(LOGIN);
printf("请输入姓名>>>");
fgets(msg.name, 20, stdin);
msg.name[strlen(msg.name)-1] = 0;
//发送登录信息sendto
if(sendto(cfd, &msg, sizeof(msg), 0, (void*)&sin, sizeof(sin)) < 0){
PRINT_ERR("sendto");
return -1;
}
pid_t pid = fork();
if(pid > 0){
//父进程获取信息
do_recv(cfd);
}
else if(0 == pid){
//子进程发送信息
do_chat(cfd, msg, sin);
}
//关闭套接字
close(cfd);
return 0;
}
/*
* function: 聊天
* @param [ in] 套接字,信息,服务器信息
* @param [out]
* @return 成功返回0,失败返回-1
*/
int do_chat(int cfd, MSG msg, struct sockaddr_in sin){
while(1){
//从终端获取聊天信息
bzero(msg.text, sizeof(msg.text));
fgets(msg.text, sizeof(msg.text),stdin);
msg.text[strlen(msg.text)-1] = 0;
//如果是聊天信息,则封装上 CHAT协议
//如果是退出信息,则封装上 QUIT协议
if(strncasecmp(msg.text, "quit" , 4) == 0){
msg.type = htonl(QUIT);
}
else{
msg.type = htonl(CHAT);
}
//发送
if(sendto(cfd, &msg, sizeof(msg), 0, (void*)&sin, sizeof(sin)) < 0){
PRINT_ERR("sendto");
return -1;
}
//如果是退出信息,则客户端要退出
//子进程:即当前进程,需要退出
//且父进程也要退出
if(msg.type == htonl(QUIT)){
exit(0); //退出子进程;
}
}
}
/*
* function: 接收信息
* @param [ in] 套接字
* @param [out]
* @return 成功返回0,失败返回-1;
*/
int do_recv(int cfd){
MSG rcv_msg ;
while(1){
if(recvfrom(cfd, &rcv_msg, sizeof(rcv_msg), 0, NULL, NULL) < 0){
PRINT_ERR("recvfrom");
return -1;
}
printf("%s\n",rcv_msg.text);
}
}