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 ? ? 效果如下:
轉載于:https://www.cnblogs.com/ysjd/p/7709480.html
總結
- 上一篇: Appium 常见API 四(三种等待方
- 下一篇: mysql主从部署