select 函数实现 三种拓扑结构 n个客户端的异步通信 (完全图+线性链表+无环图)
来源:互联网 发布:防止软件自动安装 编辑:程序博客网 时间:2024/06/16 04:49
一、这里只介绍简单的三个客户端异步通信(完全图拓扑结构)
1 1 //建立管道2 2 mkfifo 12 13 21 23 31 32
open顺序:
cl1 读 , cl2 cl3 向 cl1写
cl2 读 , cl1 cl3 向 cl2写
cl3 读 , cl1 cl2 向 cl3写
顺序的规律就是 第i个 客户端读 其他各个客户端 ,其他的各个客户端 向 i 写 ,i 从 1 到 3.
cl1 代码:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<unistd.h> 5 #include<sys/stat.h> 6 #include<sys/types.h> 7 #include<fcntl.h> 8 #include <sys/time.h> 9 #include<sys/select.h>10 #include <sys/select.h>11 12 /* According to earlier standards */13 #include <sys/time.h>14 #include <sys/types.h>15 #include <unistd.h>16 17 int main(int argc, char* argv[])//2118 {19 20 int fd21, fd31,fd12,fd13 ;21 fd21 = open("21", O_RDONLY);22 fd31 = open("31", O_RDONLY);23 24 fd12 = open("12",O_WRONLY);25 26 fd13 = open("13",O_WRONLY);27 printf("OK!\n");28 29 30 printf("OK!\n");31 fd_set read_sets ;32 fd_set write_sets ;33 int iret,iwrt ;34 char buf[1024] ;35 struct timeval tm ;36 while(1)37 {38 39 tm.tv_sec = 1 ;40 tm.tv_usec = 0 ;41 FD_ZERO(&read_sets);42 FD_ZERO(&write_sets);43 44 FD_SET(fd21, &read_sets);45 FD_SET(fd31, &read_sets);46 FD_SET( 0, &write_sets);47 //FD_SET(fd12, &write_sets);48 //FD_SET(fd13, &write_sets);49 50 iret = select(10, &read_sets, NULL, NULL, &tm);51 iwrt = select(10,&write_sets,NULL,NULL,&tm);52 53 //读54 if(iret != 0)55 {56 printf("active: %d\n", iret);57 58 if(FD_ISSET(fd21, &read_sets))59 {60 memset(buf, 0, 1024);61 read(fd21, buf, 1023);62 printf("from 2: %s\n", buf);63 }64 if(FD_ISSET(fd31, &read_sets))65 {66 memset(buf, 0, 1024);67 read(fd31, buf, 1023);68 printf("from 3: %s\n", buf);69 }70 }71 72 73 // write74 if(iwrt != 0)75 {76 printf("active: %d\n", iwrt);77 if(FD_ISSET( 0 /*fd12*/, &write_sets))78 {79 memset(buf, 0, 128);80 read(0, buf, 127) ;81 write(fd12, buf, strlen(buf));82 write(fd13, buf, strlen(buf));83 }84 /*if(FD_ISSET(fd13, &write_sets))85 {86 memset(buf, 0, 128);87 read(0, buf, 127) ;88 write(fd13, buf, strlen(buf));89 }*/90 }91 92 }93 return 0 ;94 }
cl2 代码:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<unistd.h> 5 #include<sys/stat.h> 6 #include<sys/types.h> 7 #include<fcntl.h> 8 #include<sys/select.h> 9 int main(int argc, char* argv[])//2110 {11 int fd12, fd32,fd21,fd23 ;12 fd21 = open("21",O_WRONLY);13 14 fd12 = open("12", O_RDONLY);15 fd32 = open("32", O_RDONLY);16 17 fd23 = open("23",O_WRONLY);18 19 20 fd_set read_sets ,write_sets ;21 int iret ,iwrt;22 char buf[1024] ;23 struct timeval tm ;24 while(1)25 {26 27 tm.tv_sec = 1 ;28 tm.tv_usec = 0 ;29 FD_ZERO(&read_sets);30 FD_ZERO(&write_sets);31 FD_SET(fd12, &read_sets);32 FD_SET(fd32, &read_sets);33 FD_SET( 0, &write_sets);34 //FD_SET(fd21,&write_sets);35 //FD_SET(fd23,&write_sets);36 37 iret = select(10, &read_sets, NULL, NULL, &tm);38 iwrt = select(10,&write_sets,NULL,NULL,&tm);39 40 if(iret != 0)41 {42 printf("active: %d\n", iret);43 44 if(FD_ISSET(fd12, &read_sets))45 {46 memset(buf, 0, 1024);47 read(fd12, buf, 1023);48 printf("from 1: %s\n", buf);49 }50 if(FD_ISSET(fd32, &read_sets))51 {52 memset(buf, 0, 1024);53 read(fd32, buf, 1023);54 printf("from 3: %s\n", buf);55 }56 }57 58 59 // write60 if(iwrt != 0)61 {62 printf("active: %d\n", iwrt);63 if(FD_ISSET( 0 , &write_sets))64 {65 memset(buf, 0, 128);66 read(0, buf, 127) ;67 write(fd21, buf, strlen(buf));68 write(fd23, buf, strlen(buf));69 }70 /* if(FD_ISSET(fd23, &write_sets))71 {72 memset(buf, 0, 128);73 read(0, buf, 127) ;74 write(fd23, buf, strlen(buf));75 }*/76 }77 78 }79 return 0 ;80 }
cl3 代码:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<unistd.h> 5 #include<sys/stat.h> 6 #include<sys/types.h> 7 #include<fcntl.h> 8 #include<sys/select.h> 9 int main(int argc, char* argv[])//3110 {11 int fd13, fd23,fd31,fd32 ;12 fd31 = open("31",O_WRONLY);13 14 fd32 = open("32",O_WRONLY);15 16 fd13 = open("13", O_RDONLY);17 fd23 = open("23", O_RDONLY);18 19 printf("OK!\n");20 fd_set read_sets ,write_sets ;21 int iret,iwrt ;22 char buf[1024] ;23 struct timeval tm ;24 while(1)25 {26 27 tm.tv_sec = 1 ;28 tm.tv_usec = 0 ;29 FD_ZERO(&read_sets);30 FD_ZERO(&write_sets);31 FD_SET(fd13, &read_sets);32 FD_SET(fd23, &read_sets);33 //FD_SET(fd31,&write_sets);34 //FD_SET(fd32,&write_sets);35 FD_SET( 0, &write_sets);36 37 iret = select(10, &read_sets, NULL, NULL, &tm);38 iwrt = select(10,&write_sets,NULL,NULL,&tm);39 40 //读41 if(iret != 0)42 {43 printf("active: %d\n", iret);44 45 if(FD_ISSET(fd13, &read_sets))46 {47 memset(buf, 0, 1024);48 read(fd13, buf, 1023);49 printf("from 1: %s\n", buf);50 }51 if(FD_ISSET(fd23, &read_sets))52 {53 memset(buf, 0, 1024);54 read(fd23, buf, 1023);55 printf("from 2: %s\n", buf);56 }57 }58 59 60 // write61 if(iwrt != 0)62 {63 printf("active: %d\n", iwrt);64 if(FD_ISSET( 0 , &write_sets))65 {66 memset(buf, 0, 128);67 read(0, buf, 127) ;68 write(fd31, buf, strlen(buf));69 write(fd32, buf, strlen(buf));70 }71 /*if(FD_ISSET(fd32, &write_sets))72 {73 memset(buf, 0, 128);74 read(0, buf, 127) ;75 write(fd32, buf, strlen(buf));76 }*/77 }78 }79 80 return 0 ;81 }
二 、n个客户端异步通信 (线性链表的拓扑结构)
很显然的,如果用上述的方法需要每个客户端和其他客户端都直接相邻,即完全图。
建立n个客户端通信,需要 2*((n-1)+(n-2)+(n-3)+……3+2+1) = 2*(n-1 + 1)*(n -1)/2 =n * (n-1) 根管道,
这么多的管道连接会使得代码实现变得非常冗杂、而且系统浪费资源管道。
这里,用线性链表的拓扑结构,可以解决这个问题:
1、 客户端以线性存储
2、 当 pre 发来数据时, 打印出来,并且转发给next(若next存在)。
3、 当 next 发来数据时, 打印出来,并且转发给pre(若pre存在)。
4、 当键盘发来数据时,转发给next(若next存在),转发给pre(若pre存在)。
例子:
1、客户端拓扑结构为 1——3——2——4
在文件存储如下:
2、我还编写一个读取topo.txt 文件 ,自动生成管道的代码:
BuildFIFO.cpp 如下:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<string> 5 #include<unistd.h> 6 #include<sys/stat.h> 7 #include<sys/types.h> 8 #include<fcntl.h> 9 #include <sys/time.h>10 #include<sys/select.h>11 using namespace std;12 int main(int argc, char* argv[])//2113 {14 15 FILE* topu = fopen("topo.txt","r");16 int fir = 1;17 char dir[5],DIR[11];18 string str1,str2,str ;19 while(!feof(topu))20 {21 fscanf(topu ,"%s\n",dir);22 str1 = dir;23 if(fir)24 {25 fir =0 ;26 str2=str1;27 continue;28 }29 str=str1+"T"+str2;30 strcpy(DIR,str.c_str());31 mkfifo(DIR,0777);32 33 str=str2+"T"+str1;34 strcpy(DIR,str.c_str());35 mkfifo(DIR,0777);36 str2 = str1;37 }38 39 fclose(topu);40 41 return 0;42 }
3、从客户端3键盘输入数据后,发送到各个客户端:
4、这里也有个 open 的 顺序的问题,但其实这种拓扑结构很好解决这个问题:
只需要每个相邻的客户端 读写顺序相反就能解决了
如下:
1 if(count & 1== 1) //判断节点的位置是奇数 还是 偶数 ,如果是 奇数 就 先读后写 2 { 3 if(strcmp("-1",pre->val)!=0) 4 { 5 6 fdReadFromPre = My_Open(pre->val,p->val,0); 7 fdWriteToPre = My_Open(p->val,pre->val,1); 8 } 9 10 if(p->next!=NULL)11 {12 fdReadFromNext = My_Open(p->next->val,p->val,0);13 fdWriteToNext = My_Open(p->val,p->next->val,1);14 }15 }16 else //如果是偶数,先写后读17 {18 if(strcmp("-1",pre->val)!=0)19 {20 fdWriteToPre = My_Open(p->val,pre->val,1);21 fdReadFromPre = My_Open(pre->val,p->val,0);22 }23 24 if(p->next!=NULL)25 {26 fdWriteToNext = My_Open(p->val,p->next->val,1);27 fdReadFromNext = My_Open(p->next->val,p->val,0);28 }29 30 }
5、各客户端代码:
这里只发 cl1.cpp
(
其他客户端就是
1 while( strcmp("1",p->val)!=0)
1 char tembuf[1024] = "Form1 :";
这两句代码不一样而已
)
如下:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<unistd.h> 5 #include<sys/stat.h> 6 #include<sys/types.h> 7 #include<fcntl.h> 8 #include <sys/time.h> 9 #include<sys/select.h> 10 11 12 #define fdNULL -9999 13 14 struct node 15 { 16 char val[5]; 17 node* next; 18 }; 19 20 int My_Open(char A[],char B[],int type) 21 { 22 char Cstr[11]; 23 memset( Cstr, '\0', sizeof(Cstr) ); 24 strcat(Cstr,A); 25 strcat(Cstr,"T"); 26 strcat(Cstr,B); 27 if(type == 0) return open(Cstr, O_RDONLY); 28 else return open(Cstr, O_WRONLY); 29 } 30 31 32 int main(int argc, char* argv[])//21 33 { 34 35 FILE* topu = fopen("/home/soso/Desktop/1-30/LineSelect/topo.txt","r"); 36 char a[5]; 37 38 node* L = (node*)calloc(1, sizeof(node)); //save topo 39 strcpy(L->val,"-1"); 40 L->next = NULL; 41 node* tem , *p ,*pre; 42 p=L; 43 while(!feof(topu)) 44 { 45 fscanf(topu ,"%s\n",a); 46 tem= (node*)calloc(1, sizeof(node)); 47 strcpy(tem->val,a); 48 tem->next = NULL; 49 p->next=tem; 50 p=p->next; 51 } 52 fclose(topu); 53 54 pre=L; 55 p= L->next; 56 int count = 1; 57 while( strcmp("1",p->val)!=0) 58 { 59 p=p->next; 60 pre=pre->next; 61 ++count; 62 } 63 64 int fdReadFromPre,fdReadFromNext,fdWriteToPre,fdWriteToNext ; 65 fdReadFromPre=fdReadFromNext=fdWriteToPre=fdWriteToNext=fdNULL; 66 if(count & 1== 1) //判断节点的位置是奇数 还是 偶数 ,如果是 奇数 就 先读后写 67 { 68 if(strcmp("-1",pre->val)!=0) 69 { 70 71 fdReadFromPre = My_Open(pre->val,p->val,0); 72 fdWriteToPre = My_Open(p->val,pre->val,1); 73 } 74 75 if(p->next!=NULL) 76 { 77 fdReadFromNext = My_Open(p->next->val,p->val,0); 78 fdWriteToNext = My_Open(p->val,p->next->val,1); 79 } 80 } 81 else //如果是偶数,先写后读 82 { 83 if(strcmp("-1",pre->val)!=0) 84 { 85 fdWriteToPre = My_Open(p->val,pre->val,1); 86 fdReadFromPre = My_Open(pre->val,p->val,0); 87 } 88 89 if(p->next!=NULL) 90 { 91 fdWriteToNext = My_Open(p->val,p->next->val,1); 92 fdReadFromNext = My_Open(p->next->val,p->val,0); 93 } 94 95 } 96 97 printf("OK!\n"); 98 99 fd_set read_sets ;100 fd_set write_sets ;101 int iret,iwrt ;102 char buf[1024] ;103 struct timeval tm ;104 while(1)105 {106 107 tm.tv_sec = 1 ;108 tm.tv_usec = 0 ;109 FD_ZERO(&read_sets);110 FD_ZERO(&write_sets);111 if(fdReadFromPre != fdNULL)112 FD_SET(fdReadFromPre, &read_sets);113 if(fdReadFromNext != fdNULL)114 FD_SET(fdReadFromNext, &read_sets);115 FD_SET( 0, &write_sets);116 117 118 iret = select(10, &read_sets, NULL, NULL, &tm);119 iwrt = select(10,&write_sets,NULL,NULL,&tm);120 121 //读122 if(iret != 0)123 {124 125 if(FD_ISSET(fdReadFromPre, &read_sets))126 {127 memset(buf, 0, 1024);128 read(fdReadFromPre, buf, 1023);129 if(fdWriteToNext!=fdNULL) //把从pre读过来的数据转发到next去130 write(fdWriteToNext, buf, strlen(buf));131 printf("%s\n" ,buf);132 }133 if(FD_ISSET(fdReadFromNext, &read_sets))134 {135 memset(buf, 0, 1024);136 read(fdReadFromNext, buf, 1023);137 if(fdWriteToPre!=fdNULL) //把从next读过来的数据转发到pre去138 write(fdWriteToPre, buf, strlen(buf));139 printf("%s\n", buf);140 }141 }142 143 144 // write145 if(iwrt != 0)146 {147 148 if(FD_ISSET( 0 , &write_sets))149 {150 memset(buf, 0, 128);151 read(0, buf, 127) ;152 char tembuf[1024] = "Form1 :";153 strcat(tembuf,buf);154 if(fdWriteToNext!=fdNULL) //把从键盘输入的数据向next、pre 转发155 write(fdWriteToNext, tembuf, strlen(tembuf));156 if(fdWriteToPre!=fdNULL)157 write(fdWriteToPre, tembuf, strlen(tembuf));158 }159 }160 161 }162 return 0;163 }
6、添加的客户端
1、在topo.txt 添加 客户名 再 换行
2、再按一下 已经生成的 BuildFIFO 可执行文件,及自动生成所需的管道
3、vim 出客户端,代码只需 改动两处(见5) 便可以完成客户端的添加。
三 、n个客户端异步通信 (无环图的拓扑结构)
线性拓扑结构有个很大的缺陷
如图:
客户端1 发送消息,要经过 3、2 的转发才能到达 4。当客户端数量很大时,链表前部和后部之间的通信的延迟会很大。
如果改进,用树形拓扑机构就会很大的缓解这个问题。
1、 《计算机网络》的OSPF路由算法里面提到的泛洪法+无环图拓扑结构
如图 为Zhu客户端键盘输入数据:
2、存储结构
在文件topo.txt 中以类似于邻接的方式存储:
topo文件格式为:
顶点 节点个数 节点1 节点2 ……
如图:
客户端读取文件后的邻接表存储代码:
1 map<string,bool> visit; 2 3 struct TreeLine 4 { 5 vector<string> TreeNode; 6 int level; //层号 7 }; 8 9 10 map<string,TreeLine> Tree;
1 FILE* topu = fopen("topo.txt","r"); 2 int fir = 1; 3 int i,j; 4 char strtem[5],strtem2[5],tem,Lval[5]; 5 int num; 6 while(!feof(topu)) 7 { 8 fscanf(topu ,"%s %d",strtem,&num); 9 if(fir) //记录第一个客户端的名称10 {11 fir = 0;12 strcpy(Lval,strtem);13 }14 15 16 TreeLine TemLine;17 for(int i =0 ;i< num;i++)18 {19 fscanf(topu," %s",strtem2);20 TemLine.TreeNode.push_back(strtem2);21 }22 fgetc(topu);23 24 Tree[strtem]=TemLine;25 visit[strtem] = false; //初始化访问位26 }27 fclose(topu);
3、DFS来标注奇偶层号,判断open顺序(只要奇偶层顺序相反)
1 void DFS(string val,int level) 2 { 3 visit[val] = true ; 4 Tree[val].level = level; 5 //cout<<val<<":"<<level<<" "<<Tree[val].TreeNode.size()<<endl; 6 int i; 7 for(i = 0;i<Tree[val].TreeNode.size();++i) 8 { 9 if(visit[Tree[val].TreeNode[i]] == false)10 DFS(Tree[val].TreeNode[i],level+1);11 }12 }
1 int level = 1; 2 DFS(Lval,level); 3 4 vector<int> fdReadOpen,fdWriteOpen; 5 6 7 string TemString; 8 if(Tree[UserName].level & 1 == 1) //判断层号 奇数先读后写 9 {10 for(i= 0 ;i<Tree[UserName].TreeNode.size();++i)11 {12 TemString=Tree[UserName].TreeNode[i]+"TO"+UserName;13 fdReadOpen.push_back(open(TemString.c_str(), O_RDONLY));14 }15 16 for(i= 0 ;i<Tree[UserName].TreeNode.size();++i)17 {18 TemString = UserName;19 TemString+="TO"+Tree[UserName].TreeNode[i];20 fdWriteOpen.push_back(open(TemString.c_str(),O_WRONLY));21 }22 23 }24 else //判断层号 偶数数先写后读25 {26 for(i= 0 ;i<Tree[UserName].TreeNode.size();++i)27 {28 TemString = UserName;29 TemString+="TO"+Tree[UserName].TreeNode[i];30 fdWriteOpen.push_back(open(TemString.c_str(),O_WRONLY));31 }32 33 for(i= 0 ;i<Tree[UserName].TreeNode.size();++i)34 {35 TemString=Tree[UserName].TreeNode[i]+"TO"+UserName;36 fdReadOpen.push_back(open(TemString.c_str(), O_RDONLY));37 }38 }
3、各客户端代码:
这次用了宏定义,每个客户端只需修改:
1 #define UserName "Ye"
其他代码都相同。
这里分析客户端 Ye 的代码:
1 #include <vector> 2 #include<map> 3 #include<string> 4 #include<iostream> 5 #include<stdio.h> 6 #include<stdlib.h> 7 #include<string.h> 8 #include<unistd.h> 9 #include<sys/stat.h> 10 #include<sys/types.h> 11 #include<fcntl.h> 12 #include <sys/time.h> 13 #include<sys/select.h> 14 using namespace std; 15 16 #define MaxSize 10000 17 18 #define UserName "Ye" 19 20 map<string,bool> visit; 21 22 struct TreeLine 23 { 24 vector<string> TreeNode; 25 int level; //层号 26 }; 27 28 29 map<string,TreeLine> Tree; 30 31 void DFS(string val,int level) 32 { 33 visit[val] = true ; 34 Tree[val].level = level; 35 //cout<<val<<":"<<level<<" "<<Tree[val].TreeNode.size()<<endl; 36 int i; 37 for(i = 0;i<Tree[val].TreeNode.size();++i) 38 { 39 if(visit[Tree[val].TreeNode[i]] == false) 40 DFS(Tree[val].TreeNode[i],level+1); 41 } 42 } 43 44 45 46 int main(int argc, char* argv[]) 47 { 48 49 FILE* topu = fopen("topo.txt","r"); 50 int fir = 1; 51 int i,j; 52 char strtem[5],strtem2[5],tem,Lval[5]; 53 int num; 54 while(!feof(topu)) 55 { 56 fscanf(topu ,"%s %d",strtem,&num); 57 if(fir) //记录第一个客户端的名称 58 { 59 fir = 0; 60 strcpy(Lval,strtem); 61 } 62 63 64 TreeLine TemLine; 65 for(int i =0 ;i< num;i++) 66 { 67 fscanf(topu," %s",strtem2); 68 TemLine.TreeNode.push_back(strtem2); 69 } 70 fgetc(topu); 71 72 Tree[strtem]=TemLine; 73 visit[strtem] = false; //初始化访问位 74 } 75 fclose(topu); 76 77 int level = 1; 78 DFS(Lval,level); 79 80 vector<int> fdReadOpen,fdWriteOpen; 81 82 83 string TemString; 84 if(Tree[UserName].level & 1 == 1) //判断层号 奇数先读后写 85 { 86 for(i= 0 ;i<Tree[UserName].TreeNode.size();++i) 87 { 88 TemString=Tree[UserName].TreeNode[i]+"TO"+UserName; 89 fdReadOpen.push_back(open(TemString.c_str(), O_RDONLY)); 90 } 91 92 for(i= 0 ;i<Tree[UserName].TreeNode.size();++i) 93 { 94 TemString = UserName; 95 TemString+="TO"+Tree[UserName].TreeNode[i]; 96 fdWriteOpen.push_back(open(TemString.c_str(),O_WRONLY)); 97 } 98 99 }100 else //判断层号 偶数数先写后读101 {102 for(i= 0 ;i<Tree[UserName].TreeNode.size();++i)103 {104 TemString = UserName;105 TemString+="TO"+Tree[UserName].TreeNode[i];106 fdWriteOpen.push_back(open(TemString.c_str(),O_WRONLY));107 }108 109 for(i= 0 ;i<Tree[UserName].TreeNode.size();++i)110 {111 TemString=Tree[UserName].TreeNode[i]+"TO"+UserName;112 fdReadOpen.push_back(open(TemString.c_str(), O_RDONLY));113 }114 }115 116 117 118 119 printf("OK!\n");120 121 fd_set read_sets ;122 fd_set write_sets ;123 int iret,iwrt ;124 char buf[1024] ;125 struct timeval tm ;126 while(1)127 {128 129 tm.tv_sec = 1 ;130 tm.tv_usec = 0 ;131 FD_ZERO(&read_sets);132 FD_ZERO(&write_sets);133 for(i=0;i<fdReadOpen.size();i++)134 FD_SET(fdReadOpen[i], &read_sets);135 FD_SET( 0, &write_sets);136 137 iret = select(1023, &read_sets, NULL, NULL, &tm);138 iwrt = select(1023,&write_sets,NULL,NULL,&tm);139 140 //读141 if(iret != 0)142 {143 144 for(i=0;i<fdReadOpen.size();i++) //遍历ReadOpen145 {146 if(FD_ISSET(fdReadOpen[i], &read_sets)) //当收到ReadOpen[i]时147 {148 memset(buf, 0, 1024);149 read(fdReadOpen[i], buf, 1023);150 printf("%s\n" ,buf); //打印出来151 for(j=0;j<fdWriteOpen.size();j++) //向其他客户端转发152 {153 if(j != i) //AtoB 和 BtoA 的fdOpen存储位置是对应的154 write(fdWriteOpen[j], buf, strlen(buf));155 }156 }157 }158 }159 160 161 // write162 if(iwrt != 0)163 {164 if(FD_ISSET( 0 , &write_sets))165 {166 memset(buf, 0, 128);167 read(0, buf, 127) ;168 char tembuf[1024] = UserName;169 strcat(tembuf," :");170 strcat(tembuf,buf);171 for(i =0 ;i< fdWriteOpen.size();i++)172 write(fdWriteOpen[i], tembuf, strlen(tembuf));173 }174 }175 176 }177 178 179 return 0;180 }
4、添加的客户端
1、按照输入格式在topo.txt 添加
2、再按一下 已经生成的 BuildFIFO 可执行文件,及自动生成所需的管道
3、vim 出客户端,代码只需 改动一处(见3) 便可以完成客户端的添加。
- select 函数实现 三种拓扑结构 n个客户端的异步通信 (完全图+线性链表+无环图)
- select 函数实现 三种拓扑结构 n个客户端的异步通信 (完全图+线性链表+无环图)
- select函数 实现三用户简单通信
- Unity中的Socket通信(多个客户端的异步通信)
- Linux下网络socket编程——实现服务器(select)与多个客户端通信
- (三)TCP用select函数处理多个客户端连接(非阻塞模式)
- 网络拓扑结构的绘制(三)
- 线性表 链表结构的实现
- 返回线性链表的倒数第n个元素
- 采用异步socket实现客户端和服务端的通信
- python使用select实现异步通信
- Python使用select实现异步通信
- 线性表的实现(三)循环链表
- 数据结构(三):线性表的链式存储结构
- 线性表的链式存储结构(三)
- 终于完成~《数据结构》实验二:线性表的实验(实现一个N个学生成绩的顺序表)
- 客户端和服务端通讯的N种方式(三)
- 客户端和服务端通讯的N种方式(三)
- [LeetCode][12]Integer to Roman解析 int转罗马字符时间复杂度为常数的实现-Java实现
- 使用ajax和history.pushState无刷新改变页面URL
- Android 中的回调函数揭秘
- C#项目中发生PInvokeStackImbalance异常,堆栈不对称异常
- 如何在eclipse中使用反编译插件
- select 函数实现 三种拓扑结构 n个客户端的异步通信 (完全图+线性链表+无环图)
- Spring Boot实践折腾记汇总
- 1004. Counting Leaves (30)
- 今年暑假不AC
- FatMouse
- 1065. A+B and C (64bit)
- 1005Spell It Right (20)
- 1006. Sign In and Sign Out
- 1009. Product of Polynomials (25)