I/O多路复用

  1 #include"pack.h"
  2 
  3 /****************************************************/
  4 //用户保存caddr的链表
  5 void add_node_caddr(int confd,struct sockaddr_in caddr)
  6 {
  7     struct online_c *temp=(struct online_c *)malloc(sizeof(struct online_c))
  8 ;   
  9     temp->confd=confd;
 10     temp->caddr=caddr;
 11     temp->next=c_head;
 12     c_head=temp;
 13 }   
 14 
 15 void delete_C_node(int confd)
 16 {
 17     if(c_head==NULL)
 18         return ;
 19     struct online_c * p=NULL;
 20     if(c_head->confd==confd && c_head->next==NULL)
 21     {
 22         free(c_head);
 23         c_head=NULL;
 24         return ;
 25     }
 26     else if(c_head->confd==confd && c_head->next!=NULL)
 27     {
 28         p=c_head->next;
 29         free(c_head);
 30         c_head=p;
 31         return ;
 32     }
 33     p=c_head;
 34 
 35     struct online_c * q=NULL;
 36     while(p->next!=NULL)
 37     {
 38         if(p->next->confd==confd)
 39         {
 40             q=p->next;
 41             p->next=q->next;
 42             free(q);
 43             return ;
 44         }
 45         p=p->next;
 46     }
 47     printf("该节点不存在\n");
 48     return ;
 49 }
 50 
 51 struct sockaddr_in  search_caddr(int confd)
 52 {
 53     struct online_c * p=c_head;
 54     while(p!=NULL)
 55     {
 56         if(p->confd==confd)
 57             return p->caddr;
 58         p=p->next;
 59     }
 60 }
 61 
 62 /***********************用于保存在线用户的链表*********
 63 *********************/
 64 void add_node(int confd,int id)
 65 {
 66     Pmen temp=(Pmen)malloc(sizeof(Men));
 67     temp->data.id=id;
 68     temp->data.confd=confd;
 69 
 70 
 71     temp->data.caddr=search_caddr(confd);
 72 
 73     delete_C_node(confd);
 74     temp->next=head;
 75     head=temp;
 76     return ;
 77 }
 78 
 79 void show_link()
 80 {
 81     Pmen p=head;
 82     printf("id\tconfd\tport\taddr\n");
 83     char addr[20];
 84     while(p!=NULL)
 85     {
 86         printf("%d\t%d\t%d\t%s\n",p->data.id,p->data.confd,\
 87                 ntohs(p->data.caddr.sin_port),\
 88                 inet_ntop(AF_INET,&(p->data.caddr.sin_addr.s_addr)
 89 ,addr,sizeof(addr)));
 90         p=p->next;
 91     }
 92 }
 93 
 94 void delete_node(int confd)
 95 {
 96     Pmen p=NULL;
 97     if(head->data.confd==confd && head->next==NULL)
 98     {
 99         free(head);
100         head=NULL;
101         return ;
102     }
103     else if(head->data.confd==confd && head->next!=NULL)
104     {
105     {
106         p=head->next;
107         free(head);
108         head=p;
109         return ;
110     }
111     p=head;
112 
113     Pmen q=NULL;
114     while(p->next!=NULL)
115     {
116         if(p->next->data.confd==confd)
117         {
118             q=p->next;
119             p->next=q->next;
120             free(q);
121             return ;
122         }
123         p=p->next;
124     }
125     printf("该节点不存在\n");
126     return ;
127 }
128 
129 int search_confd(int id)
130 {
131     Pmen p=head;
132     while(p!=NULL)
133     {
134         if(p->data.id==id)
135             return p->data.confd;
136         p=p->next;
137     }
138     return -1;
139 }
140 
141 int search_id(int confd)
142 {
143     Pmen p=head;
144     while(p!=NULL)
145     {
146         if(p->data.confd==confd)
147             return p->data.id;
148         p=p->next;
149     }
150     return -1;
151 }
link.c
 1 #ifndef __PACK_H_
 2 #define __PACK_H_
 3 #include<sys/socket.h>
 4 #include<sys/types.h>
 5 #include<stdio.h>
 6 #include<netinet/in.h>
 7 #include<arpa/inet.h>
 8 #include<errno.h>
 9 #include<string.h>
10 #include<stdlib.h>
11 #include<unistd.h>
12 #include <sys/time.h>
13 #include <sys/types.h>
14 #include <unistd.h>
15 
16 struct pack//用户封包
17 {
18     int type;
19     int len;
20     char buf[0];
21 };
22 
23 struct DATA //用登录和注册
24 {
25     int confd;
26     int flag;
27     int id;
28     char name[20];
29     char passwd[20];
30     struct sockaddr_in caddr;
31 };
32 typedef struct online//用户在线用户链表
33 {
34     struct DATA data;
35     struct online *next;
36 }Men,*Pmen;
37 
38 struct message//用于发送信息
39 {
40     int id;//who your want to send
41     char buf[20];//message
42 };
43 
44 struct online_c//用户保存链接了但是没登录的客户端的caddr
45 {
46     int confd;
47     struct sockaddr_in caddr;
48     struct online_c *next;
49 };
50 void myunpack(int confd,struct pack temp);
51 void login(int confd);
52 void person_register(int confd);
53 void send_message(int confd,int len);
54 
55 void add_node(int confd,int id);
56 void delete_node(int confd);
57 
58 int search_confd(int id);
59 int search_id(int );
60 
61 void show_link();
62 struct online * head;
63 
64 struct online_c *c_head;
65 void add_node_caddr(int confd,struct sockaddr_in caddr);
66 void delete_C_node(int confd);
67 struct sockaddr_in  search_caddr(int confd);
68 
69 #endif
pack.h
  1 #include"pack.h"
  2 #include<mysql/mysql.h>
  3 
  4 void send_message(int confd,int len)
  5 {
  6     printf("on send message\n");
  7     struct message temp;
  8     int ret=read(confd,&temp,sizeof(temp));
  9 
 10     int sendfd=search_confd(temp.id);
 11     printf("sendfd=%d id=%d\n",sendfd,temp.id);
 12     if(sendfd==-1)
 13         return ;
 14     int id=search_id(confd);
 15     temp.id=id;
 16 
 17     write(sendfd,&temp,sizeof(temp));
 18     printf("ret=%d %s\n",ret,temp.buf);
 19     return ;
 20 }
 21 
 22 
 23 void myunpack(int confd,struct pack temp)
 24 {
 25 
 26     switch(temp.type)
 27     {
 28         case 1:
 29                 login(confd);
 30                 break;
 31         case 2: person_register(confd);
 32                 break;
 33         case 3:
 34                 send_message(confd,temp.len);
 35                 break;
 36         default:
 37                 printf("%s default\n",__func__);
 38                 return ;
 39     }
 40 }
 41 
 42 void login(int confd)
 43 {
 44     struct DATA temp;
 45     int ret=read(confd,&temp,sizeof(struct DATA));//读取登录信息
 46     if(ret<=0)
 47     {
 48         printf("read login pack error\n");
 49         close(confd);
 50         return ;
 51     }
 52     MYSQL *conn;
 53     conn=mysql_init(NULL);
 54     if(!mysql_real_connect(conn,"localhost","root","513920","membe
 55 r",0,NULL,0))
 56     {
 57         printf("connect mysql error\n");
 58         temp.flag=-1;
 59         write(confd,&temp,sizeof(temp));
 60         return ;
 61     }
 62     char buf[100];
 63     sprintf(buf,"select * from person where id=%d and passwd=\'%s\'",temp.id,temp.passwd);
 64     printf("%s\n",buf);
 65     if(mysql_query(conn,buf))
 66     {
 67         printf("mysql_query error\n");
 68         temp.flag=-1;
 69         write(confd,&temp,sizeof(temp));
 70         return ;
 71     }
 72     MYSQL_RES *res;
 73     MYSQL_ROW row;
 74 
 75     res=mysql_use_result(conn);
 76     row=mysql_fetch_row(res);
 77     if(row==NULL)
 78     {
 79         temp.flag=-1;
 80         printf("the person is not exist\n");
 81         write(confd,&temp,sizeof(temp));
 82         return;
 83     }
 84 
 85     temp.flag=1;
 86     strcpy(temp.name,row[1]);
 87 
 88     mysql_free_result(res);
 89     mysql_close(conn);
 90 
 91     write(confd,&temp,sizeof(temp));
 92     add_node(confd,temp.id);
 93     printf("登录成功\n");
 94     return ;
 95 }
 96 
 97 void person_register(int confd)
 98 {
 99     struct DATA temp;
100     int ret=read(confd,&temp,sizeof(struct DATA));//读取登录信息
101     if(ret<=0)
102     {
103         printf("read login pack error\n");
104         close(confd);
105         return ;
106     }
107     MYSQL *conn;
108     conn=mysql_init(NULL);
109     if(!mysql_real_connect(conn,"localhost","root","513920","membe
110 r",0,NULL,0))
111     {
112         printf("connect mysql error\n");
113         temp.flag=-1;
114         write(confd,&temp,sizeof(temp));
115         return ;
116     }
117     char buf[100];
118     sprintf(buf,"insert  into person(name,passwd) values(\'%s\',\'
119 %s\')",temp.name,temp.passwd);
120     if(mysql_query(conn,buf))
121     {
122         printf("mysql_query error\n");
123         temp.flag=-1;
124         write(confd,&temp,sizeof(temp));
125         return ;
126     }
127 
128     if(mysql_query(conn,"select max(id) as value from person"))
129     {
130         printf("mysql_query  select id error\n");
131         temp.flag=-1;
132         write(confd,&temp,sizeof(temp));
133         return ;
134 
135     }
136 
137     MYSQL_RES *res;
138     MYSQL_ROW row;
139 
140     res=mysql_use_result(conn);
141     row=mysql_fetch_row(res);
142     if(row==NULL)
143     {
144         temp.flag=-1;
145         printf("the person is not exist\n");
146         write(confd,&temp,sizeof(temp));
147         return ;
148     }
149 
150     temp.flag=1;
151     temp.id=atoi(row[0]);
152 
153     mysql_free_result(res);
154     mysql_close(conn);
155     write(confd,&temp,sizeof(temp));
156     add_node(confd,temp.id);
157     printf("注册成功\n");
158 
159     return ;
160 }
pack.c
 1 #ifndef __CPACK_H_
 2 #define __CPACK_H_
 3 #include<sys/socket.h>
 4 #include<sys/types.h>
 5 #include<stdio.h>
 6 #include<netinet/in.h>
 7 #include<arpa/inet.h>
 8 #include<errno.h>
 9 #include<string.h>
10 #include<stdlib.h>
11 #include<unistd.h>
12 #include <sys/time.h>
13 #include <sys/types.h>
14 #include <unistd.h>
15 
16 struct pack
17 {   
18     int type;
19     int len;
20     char buf[0];
21 };
22 
23 struct DATA
24 {
25     int confd;
26     int flag;
27     int id;
28     char name[20];
29     char passwd[20];
30     struct sockaddr_in caddr;
31 };
32 struct online
33 {
34     struct DATA data;
35     struct online *next;
36 };
37 
38 struct message
39 {
40     int id;//who your want to send
41     char buf[20];//message
42 };
43 
44 struct pack * mypack(int type,int len,void * buf);
45 
46 void menu(int sockfd);
47 void login(int sockfd);
48 void person_register(int sockfd);
49 
50 void send_message(int sockfd);
51 void recv_message(int sockfd);
52 
53 #endif
cpack.h
  1 #include"cpack.h"
  2 struct pack * mypack(int type,int len,void * buf)
  3 {   
  4     struct pack * temp=(struct pack *)malloc(sizeof(struct pack)+l
  5 en);
  6     temp->type=type;
  7     temp->len=len;
  8     memcpy(temp->buf,buf,len);
  9     return temp;
 10 }
 11 void menu(int sockfd)
 12 {   
 13     system("clear");
 14     printf("*******************\n");
 15     printf("* 0 exit          *\n");
 16     printf("* 1 login         *\n");
 17     printf("* 2 register      *\n");
 18     printf("*******************\n");
 19     int key;
 20     printf("please input your chioce:");
 21     scanf("%d",&key);
 22     
 23     switch(key)
 24     {
 25         case 1:
 26                 login(sockfd);
 27                 break;
 28         case 2: person_register(sockfd);
 29                 break;
 30         case 0:
 31                 exit(0);
 32                 break;
 33         default:
 34                 printf("error input\n");
 35     }
 36 }
 37 
 38 void login(int sockfd)
 39 {
 40     struct DATA temp;
 41     printf("请输入id:");
 42     scanf("%d",&temp.id);
 43     printf("请输入passwd:");
 44     scanf("%s",temp.passwd);
 45 
 46     struct pack *p=mypack(1,sizeof(temp),&temp);
 47     int ret=write(sockfd,p,sizeof(struct pack)+sizeof(temp));//将登录信息写给服务器
 48     if(ret<=0)
 49     {
 50         printf("write error\n");
 51         close(sockfd);
 52         exit(0);
 53     }
 54     ret=read(sockfd,&temp,sizeof(temp));
 55     if(ret<=0 || ret!=sizeof(temp))
 56     {
 57         printf("read login pack error\n");
 58         close(sockfd);
 59         exit(0);
 60     }
 61     if(temp.flag!=1)
 62     {
 63         printf("用户名或者密码错误\n");
 64         close(sockfd);
 65         exit(0);
 66     }
 67     printf("欢迎%s登录\n",temp.name);
 68 }
 69 
 70 void person_register(int sockfd)
 71 {
 72     struct DATA temp;
 73     printf("请输入name:");
 74     scanf("%s",temp.name);
 75     printf("请输入passwd:");
 76     scanf("%s",temp.passwd);
 77 
 78     struct pack *p=mypack(2,sizeof(temp),&temp);
 79     int ret=write(sockfd,p,sizeof(temp)+sizeof(struct pack));//将登录信息写给服务器
 80     free(p);
 81     if(ret<=0)
 82     {
 83         printf("write error\n");
 84         close(sockfd);
 85         exit(0);
 86     }
 87     ret=read(sockfd,&temp,sizeof(temp));
 88     if(ret<=0 || ret!=sizeof(temp))
 89     {
 90         printf("read login pack error\n");
 91         close(sockfd);
 92         exit(0);
 93     }
 94     if(temp.flag!=1)
 95     {
 96         printf("注册失败\n");
 97         close(sockfd);
 98         exit(0);
 99     }
100     printf("注册成功 id----%d\n",temp.id);
101 }
102 
103 void send_message(int sockfd)
104 {
105     struct message mes;
106     printf("请输入你要发送信息(1001-yisheng):");
107     scanf("%d-%s",&mes.id,mes.buf);
108 
109     struct pack * temp=mypack(3,sizeof(mes),&mes);
110     write(sockfd,temp,sizeof(struct pack)+sizeof(mes));
111     free(temp);
112 }
113 void recv_message(int sockfd)
114 {
115     struct message temp;
116     read(sockfd,&temp,sizeof(temp));
117     printf("recv from %d message:%s\n",temp.id,temp.buf);
118 }
cpack.c
  1 #include"pack.h"
  2 int main(int argc,char ** argv)
  3 {
  4     head=NULL;
  5     c_head=NULL;
  6     int listenfd;
  7 
  8     listenfd=socket(AF_INET,SOCK_STREAM,0);
  9     struct sockaddr_in myaddr;
 10     myaddr.sin_family=AF_INET;
 11     myaddr.sin_port=htons(atoi(argv[1]));
 12     inet_pton(AF_INET,"192.168.6.11",&myaddr.sin_addr.s_addr);
 13 
 14     int ret=bind(listenfd,(struct sockaddr *)&myaddr,sizeof(myaddr
 15 ));
 16     if(ret<0)
 17     {
 18         perror("bind failed:");
 19         exit(0);
 20     }
 21     ret=listen(listenfd,20);
 22     if(ret<0)
 23     {
 24         perror("listen failed:");
 25         exit(0);
 26     }
 27     struct sockaddr_in caddr;
 28     int len=sizeof(caddr);
 29     int confd;
 30     struct pack temp;
 31 
 32     fd_set set,rset;//定义一个文件描述符集合
 33     FD_ZERO(&set);//清空文件描述符集合
 34     FD_SET(listenfd,&set);//将文件描述符添加到集合里面去
 35 
 36     int maxfd=listenfd;
 37     /*
 38        int select(int nfds, fd_set *readfds, fd_set *writefds,
 39        fd_set *exceptfds, struct timeval *timeout);
 40 
 41        第一个参数:是你要监听的最大文件描述符+1
 42        返回值:如果有事件产生,返回的事件的个数.如果返回值为0,表示超时等待,出错返回负数
 43 
 44      */
 45     int nfound;
 46 
 47     while(1)
 48     {
 49         rset=set;
 50         nfound=select(maxfd+1,&rset,NULL,NULL,NULL);
 51         printf("nfound=%d\n",nfound);
 52         if(nfound<0)
 53         {
 54             perror("select error");
 55             continue;
 56         }
 57         else if(nfound==0)
 58         {
 59             printf("超时等待..\n");
 60             continue;
 61         }
 62         if(FD_ISSET(listenfd,&rset))//FD_ISSET 判断文件描述符是否有事件产生,有返回真,没有返回假
 63         {
 64             printf("accept\n");
 65             confd=accept(listenfd,(struct sockaddr*)&caddr,&len);
 66             if(confd<0)
 67             {
 68                 perror("accept failed:");
 69                 continue;
 70             }
 71             FD_SET(confd,&set);
 72             if(confd>maxfd)
 73                 maxfd=confd;
 74             FD_CLR(listenfd,&rset);//将监听的文件描述符集合中移除.
 75 
 76             add_node_caddr(confd,caddr);
 77         }
 78         for(int fd=0;fd<=maxfd;fd++)
 79         {
 80             if(fd==listenfd)
 81                 continue;
 82             if(!FD_ISSET(fd,&rset))
 83                 continue;
 84             ret=read(fd,&temp,sizeof(temp));
 85             if(ret<0)
 86             {
 87                 FD_CLR(fd,&set);//将监听的文件描述符集合中移除.
 88                 close(fd);
 89                 FD_CLR(fd,&set);//将监听的文件描述符集合中移除.
 90                 delete_node(fd);
 91                 perror("read failed:");
 92                 continue;
 93             }
 94             else if(ret==0)
 95             {
 96                 printf("client closed\n");
 97                 FD_CLR(fd,&set);//将监听的文件描述符集合中移除.
 98                 delete_node(fd);
 99                 close(fd);
100                 continue;
101             }
102             else
103             {
104                 printf("temp.type=%d\n",temp.type);
105                 myunpack(fd,temp);
106             }
107         }
108         show_link();
109     }
110 }
server.c
 1 #include<sys/socket.h>
 2 #include<sys/types.h>
 3 #include<stdio.h>
 4 #include<netinet/in.h>
 5 #include<arpa/inet.h>
 6 #include<errno.h>
 7 #include<string.h>
 8 #include<stdlib.h>
 9 #include<unistd.h>
10 #include"cpack.h"
11 int main(int argc,char ** argv)
12 {
13 //int socket(int domain, int type, int protocol);
14     int sockfd;
15     sockfd=socket(AF_INET,SOCK_STREAM,0);
16     printf("sockfd=%d\n",sockfd);
17 
18 /*
19    int  connect(int sockfd, struct sockaddr *serv_addr, int addrlen );
20     作用:向服务器请求三次握手
21     参数1:套接字
22     参数2:服务端的地址族结构,也就是地址类型,IP,端口
23     参数3:服务端地址族的大小
24     返回值:成功则返回非负数
25  */
26    struct sockaddr_in seraddr;
27     seraddr.sin_family=AF_INET;
28     seraddr.sin_port=htons(atoi(argv[1]));
29     inet_pton(AF_INET,"192.168.6.11",&seraddr.sin_addr.s_addr);
30 
31     int ret=connect(sockfd,(struct sockaddr *)&seraddr,sizeof(seraddr));
32     if(ret<0)
33     {
34         perror("connect failed:");
35         exit(0);
36     }
37 
38 //  char buf[20];
39     //scanf("%s",buf);
40 //  write(sockfd,buf,strlen(buf)+1);
41     menu(sockfd);
42 
43     pid_t pid;
44     pid=fork();
45     if(pid==0)
46     {
47         while(1)
48         {
49             send_message(sockfd);
50         }
51     }
52     else if(pid>0)
53     {
54         while(1)
55         {
56             recv_message(sockfd);
57         }
58     }
59     close(sockfd);
60 
61     return 0;
62 }
client.c
1 ALL:
2     gcc client.c cpack.c -o client
3     gcc server.c pack.c link.c -o server -lmysqlclient
4 clean:
5     rm -rf client server
Makefile

make后运行./server 7319     ./client 7319     效果如下:

posted @ 2017-10-22 13:52  时光淡了旧人心  阅读(130)  评论(0编辑  收藏  举报