多任务网络编程
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <unistd.h> 4 #include <sys/socket.h> 5 #include <netinet/in.h> 6 #include <arpa/inet.h> 7 #include "link.h" 8 9 #define PORT 8888 10 int main(void) 11 { 12 int sock_fd; 13 int conn_fd; 14 struct sockaddr_in sin;//server port 15 struct sockaddr_in cin;//client port 16 socklen_t len; 17 int ret; 18 char buf[100]; 19 fd_set read_fds; 20 int max_fd; 21 plink H; //linklist for accept 22 plink p; 23 24 init_link(&H); //linlist initilized 25 sock_fd = socket(AF_INET, SOCK_STREAM, 0); //creat soket 26 if(sock_fd < 0) 27 { 28 perror("socket"); 29 exit(1); 30 } 31 sin.sin_family = AF_INET; //fill struct for bind 32 sin.sin_port = htons(PORT); 33 inet_pton(AF_INET, "192.168.7.2", (void *)&sin.sin_addr.s_addr); 34 ret = bind(sock_fd, (struct sockaddr *)&sin, sizeof(sin)); 35 if(ret < 0) 36 { 37 perror("socket"); 38 exit(1); 39 } 40 listen(sock_fd, 10); 41 len = sizeof(cin); 42 printf("the server is listening...............\n"); 43 44 max_fd = sock_fd; 45 while(1) 46 { 47 FD_ZERO(&read_fds);//clear all the num 48 FD_SET(sock_fd, &read_fds);//set sock_fd 1 49 if(!is_empty(H)) 50 { 51 p = H->next; 52 while(p != NULL) 53 { 54 FD_SET(p->conn_fd, &read_fds); 55 p = p->next; 56 } 57 } 58 59 ret = select(max_fd + 1, &read_fds, NULL, NULL, NULL); 60 if(ret < 0) 61 { 62 perror("select"); 63 exit(1); 64 } 65 if(ret == 0) 66 { 67 printf("time out!\n"); 68 } 69 70 if(FD_ISSET(sock_fd, &read_fds))// check the num 71 { 72 conn_fd = accept(sock_fd, (struct sockaddr *)&cin, &len); 73 if(conn_fd < 0) 74 { 75 perror("accept"); 76 exit(1); 77 } 78 link_insert(H, conn_fd);//insert conn_fd into list 79 max_fd = max_fd > conn_fd?max_fd:conn_fd;//for the largest num 80 printf("IP %s is connecting \n", inet_ntoa(cin.sin_addr)); 81 } 82 83 84 if(!is_empty(H)) 85 { 86 p = H->next; 87 while(p != NULL) 88 { 89 if(FD_ISSET(p->conn_fd, &read_fds)) 90 { 91 92 { 93 ret = read(p->conn_fd, buf, 20); 94 if(ret == 0) 95 { 96 printf("IP %s is leaving \n", inet_ntoa(cin.sin_addr)); 97 p = link_delete(H,p->conn_fd); 98 } 99 printf("read: %s", buf); 100 } 101 102 } 103 p = p->next; 104 } 105 show_link(H); 106 } 107 } 108 close(sock_fd); 109 close(conn_fd); 110 111 return 0; 112 113 }
/*************************************************************************************************/
#include "link.h" void init_link(linknode **pH) { *pH = (plink)malloc(sizeof(linknode)); if(NULL == *pH) { perror("malloc"); exit(1); } (*pH)->next = NULL; } plink getlist(plink pH, int n) { plink p = pH; int j = 0; while(p->next != NULL && j<n) { p = p->next; j++; } if(j == n) return p; else return NULL; } void link_insert(plink pH, int x) { plink p; plink new; plink r = pH; p = pH->next; while(p != NULL) { r = p; p = p->next; } new = (plink)malloc(sizeof(linknode)); new->conn_fd = x; new->next = NULL; r->next = new; } plink getval(plink pH, int x) { plink p = pH->next; if(p->next == NULL) return pH; while(p && p->next->conn_fd != x) { p = p->next; } if(p != NULL) return p; else return NULL; } plink link_delete(plink pH, int x) { plink p; plink q; p = getval(pH, x); if(p != NULL) { if(pH->next == p) { // pH->next = NULL; // free(p); } q = p->next; p->next = q->next; free(q); } return p; } void invert(plink pH) { plink q; plink p = pH->next; pH->next = NULL; while(p != NULL) { q = p; p = p->next; q->next = pH->next; pH->next = q; } } bool is_empty(plink pH) { if(pH->next == NULL) return true; else return false; } void show_link(plink H) { int count = 0; plink p = H->next; while(p != NULL) { // printf("%d\t", p->conn_fd); count++; p = p->next; } printf("there are still %d guest online\n", count); }
/********************************************************************************************/
#ifndef _LINK_H #define _LINK_H #include <stdio.h> #include <stdbool.h> #include <stdlib.h> typedef struct node { int conn_fd; struct node *next; }linknode, *plink; void init_link(linknode **pH); plink getlist(plink pH, int n); void link_insert(plink pH, int x); plink getval(plink pH, int x); plink link_delete(plink pH, int x); void invert(plink pH); void show_link(plink H); #endif
/*****************************************************************************************************/
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define PORT 8888 int main(void) { int sock_fd; int conn_fd; struct sockaddr_in sin; socklen_t len; int ret; char buf[100]; sock_fd = socket(AF_INET, SOCK_STREAM, 0); if(sock_fd < 0) { perror("socket"); exit(1); } sin.sin_family = AF_INET; sin.sin_port = htons(PORT); inet_aton("192.168.7.2", &sin.sin_addr); ret = connect(sock_fd, (struct sockaddr *)&sin, sizeof(sin)); if(ret < 0) { perror("accept"); exit(1); } while(1) { fgets(buf, 1024, stdin); write(sock_fd, buf, 20); } close(sock_fd); close(conn_fd); return 0; }
程序使用slect实现多路IO的监控,下面介绍整体设计思路:
1.服务器端socket后等待accept的三次握手操作
2.握手成功后通过建立链表的形式将每次监听获得的链接存在链表的结构体中
3.服务端再确认是否有链接数据传送,有则把数据读出来
浙公网安备 33010602011771号