Socket网络编程--小小网盘程序(3)

http://www.cnblogs.com/wunaozai/p/3891062.html

接上一小节,这次增加另外的两张表,用于记录用户是保存那些文件。增加传上来的文件的文件指纹,使用MD5表示。

  两张表如下定义:

复制代码
 1 create table files(
 2 fid int,
 3 filename varchar(64),
 4 md5 varchar(64)
 5 );
 6 
 7 create table relations(
 8 uid int,
 9 fid int
10 );
复制代码

  表与表之间的关系如下:

  client.cpp 在上一小节基础上增加了一个md5的功能,传输给服务器,用于作为文件的唯一标识

复制代码
    ... 
42
struct File 43 { 44 int uid; 45 char filename[64]; 46 char md5[64]; 47 }; 48 struct FileList 49 { 50 char list[1024]; 51 }; 52 53 void print_time(char *ch);//打印时间 54 int file_push(struct Addr addr,struct User user,char *filenames); 55 int check_login(struct Addr addr,struct User * user); 56 int md5sum(char *filename,unsigned char *md5); 57 int file_pull(struct Addr addr,struct User user,char *filenames); 58 59 60 int main(int argc,char *argv[]) 61 {... 131 return 0; 132 } 133 134 //验证成功时返回大于0的uid号码,错误返回-1 135 int check_login(struct Addr addr,struct User * user) 136 {...
186 } 187 188 int file_push(struct Addr addr,struct User user,char *filenames) 189 {       ... ... 193 struct File file;//文件指纹 194 int sockfd; 195 FILE *fp; 196 char md5[64]; 197 unsigned char md5tmp[64]; 198 ... ...
220 //计算MD5 221 memset(md5,0,sizeof(md5)); 222 md5sum(filenames,md5tmp); 223 printf("计算得到的MD5:"); 224 for(int i=0;i<16;i++) 225 { 226 sprintf(&md5[i*2],"%02X",md5tmp[i]); 227 } 228 printf("%s\n",md5); 229 230 //打开文件 231 if((fp=fopen(filenames,"rb"))==NULL) 232 { 233 perror("文件打开失败"); 234 exit(-1); 235 } 236 //这里传输控制信号 237 control.control=FILE_PUSH; 238 control.uid=user.uid; 239 if(send(sockfd,(char *)&control,sizeof(struct Control),0)<0) 240 { 241 perror("控制信号发送失败"); 242 exit(-1); 243 } 244 //发送文件指纹 245 strcpy(file.filename,filenames); 246 strcpy(file.md5,md5); 247 file.uid=user.uid; 248 if(send(sockfd,(char *)&file,sizeof(struct File),0)<0) 249 { 250 perror("文件指纹发送失败"); 251 exit(-1); 252 } 253 char buffer[BUFFER_SIZE]; 254 bzero(buffer,BUFFER_SIZE); 255 printf("正在传输文件"); 256 int len=0; 257 //不断的读取文件直到文件结束 258 while((len=fread(buffer,1,BUFFER_SIZE,fp))>0) 259 { 260 if(send(sockfd,buffer,len,0)<0) 261 { 262 perror("发送数据失败"); 263 exit(-1); 264 } 265 bzero(buffer,BUFFER_SIZE); 266 printf(".");//1K打印一个点//如果要实现百分比,就要计算文件大小,然后再处理即可 267 } 268 269 printf("传输完毕\n"); 270 fclose(fp);//关闭文件流 271 close(sockfd);//关闭socket连接 272 273 return 0; 274 } 275 276 int md5sum(char *filename,unsigned char *md5) 277 { 278 MD5_CTX ctx; 279 char buffer[1024]; 280 unsigned char outmd[16]; 281 int len=0; 282 int i; 283 FILE *fp=NULL; 284 memset(outmd,0,sizeof(outmd)); 285 memset(buffer,0,sizeof(buffer)); 286 fp=fopen(filename,"rb"); 287 if(fp==NULL) 288 { 289 perror("打开文件失败"); 290 } 291 MD5_Init(&ctx); 292 while((len=fread(buffer,1,sizeof(buffer),fp))>0) 293 { 294 MD5_Update(&ctx,buffer,len); 295 memset(buffer,0,sizeof(buffer)); 296 } 297 MD5_Final(outmd,&ctx); 298 for(i=0;i<16;i++) 299 { 300 md5[i]=outmd[i]; 301 } 302 fclose(fp); 303 return 0; 304 } 305
复制代码

  server.cpp 

复制代码
    ... ...
40 struct File 41 { 42 int uid; 43 char filename[64]; 44 char md5[64]; 45 }; 46 struct FileList 47 { 48 char list[1024]; 49 }; 50 51 void print_time(char *ch);//打印时间 52 int MAX(int a,int b); 53 int mysql_check_login(struct User user); 54 int mysql_file_in(struct File file); 55 56 int mysql_get_max_fid() 57 { 58 MYSQL conn; 59 MYSQL_RES *res_ptr; 60 MYSQL_ROW result_row; 61 int res;int row;int column;int mfid; 62 char sql[256]; 63 strcpy(sql,"select max(fid) from files;"); 64 mfid=0; 65 mysql_init(&conn); 66 if(mysql_real_connect(&conn,"localhost","root","","filetranslate",0,NULL,CLIENT_FOUND_ROWS)) 67 { 68 res=mysql_query(&conn,sql); 69 if(res) 70 { 71 perror("SELECT SQL ERROR!"); 72 exit(-1); 73 } 74 else 75 { 76 res_ptr=mysql_store_result(&conn); 77 if(res_ptr) 78 { 79 column=mysql_num_fields(res_ptr); 80 row=mysql_num_rows(res_ptr)+1; 81 if(row<=1) 82 { 83 ;//没有数据 84 } 85 else 86 { 87 result_row=mysql_fetch_row(res_ptr); 88 printf("最大的fid是:%s\n",result_row[0]); 89 if(result_row[0]==NULL) 90 mfid=0; 91 else 92 mfid=atoi(result_row[0]); 93 } 94 } 95 else 96 { 97 printf("没有查询到匹配的数据\n"); 98 } 99 } 100 } 101 else 102 { 103 perror("Connect Failed!"); 104 exit(-1); 105 } 106 mysql_close(&conn); 107 return mfid; 108 } 109 110 int mysql_file_in(struct File file) 111 { 112 int mfid; 113 MYSQL conn; 114 int res; 115 char sql[256]; 116 char tmp[32]; 117 mfid=mysql_get_max_fid()+1; 118 printf("获取到的最大fid为:%d\n",mfid); 119 mysql_init(&conn); 120 if(mysql_real_connect(&conn,"localhost","root","","filetranslate",0,NULL,CLIENT_FOUND_ROWS)) 121 { 122 //insert into files values(mfid,file.filename,file.md5); 123 //insert into files values(file.uid,mfid); 124 memset(sql,0,sizeof(sql)); 125 strcpy(sql,"insert into files values("); 126 sprintf(tmp,"%d",mfid); 127 strcat(sql,tmp); 128 strcat(sql,",'"); 129 strcat(sql,file.filename); 130 strcat(sql,"','"); 131 strcat(sql,file.md5); 132 strcat(sql,"');"); 133 printf("插入的sql语句: %s\n",sql); 134 res=mysql_query(&conn,sql); 135 if(res) 136 printf("Insert Error!\n"); 137 else 138 printf("Insert Success!\n"); 139 140 memset(sql,0,sizeof(sql)); 141 strcpy(sql,"insert into relations values("); 142 sprintf(tmp,"%d",file.uid); 143 strcat(sql,tmp); 144 strcat(sql,","); 145 sprintf(tmp,"%d",mfid); 146 strcat(sql,tmp); 147 strcat(sql,");"); 148 printf("插入的sql语句: %s\n",sql); 149 res=mysql_query(&conn,sql); 150 if(res) 151 printf("Insert Error!\n"); 152 else 153 printf("Insert Success!\n"); 154 } 155 else 156 { 157 perror("Connect Failed!"); 158 exit(-1); 159 } 160 return 0; 161 } 162 163 164 int main(int argc,char *argv[]) 165 {... 201 while(1) 202 { 203 clientfd=accept(sockfd,(struct sockaddr *)&client_addr,&length); 204 if(clientfd==-1) 205 { 206 perror("accept 失败"); 207 continue; 208 } 209 printf(">>>>>%s:%d 连接成功,当前所在的ID(fd)号: %d \n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port),clientfd); 210 print_time(ch); 211 printf("加入的时间是:%s\n",ch); 212 213 //来一个连接就创建一个进程进行处理 214 pid=fork(); 215 if(pid<0) 216 { 217 perror("fork error"); 218 } 219 else if(pid==0) 220 { 221 recv(clientfd,(char *)&control,sizeof(struct Control),0); 222 printf("用户 %d 使用命令 %d\n",control.uid,control.control); 223 switch(control.control) 224 { 225 case USER_CHECK_LOGIN: 226 { 227 //身份验证处理... ...
239 break; 240 } 241 case FILE_PUSH: 242 { 243 char buffer[BUFFER_SIZE]; 244 int data_len; 245 FILE * fp=NULL; 246 struct File file; 247 //获取文件指纹 248 recv(clientfd,(char *)&file,sizeof(struct File),0); 249 printf("获取到的用户名ID: %d 文件名:%s MD5:%s\n",file.uid,file.filename,file.md5); 250 bzero(buffer,BUFFER_SIZE); 251 if((fp=fopen("data","wb"))==NULL) 252 { 253 perror("文件打开失败"); 254 exit(-1); 255 } 256 //循环接收数据 257 int size=0;//表示有多少个块 258 while(data_len=recv(clientfd,buffer,BUFFER_SIZE,0)) 259 {... ...
278 } 279 if(size>0) 280 { 281 printf("\n%s:%d的文件传送完毕\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port)); 282 //如果文件传输成功那么就可以写入数据库了 283 mysql_file_in(file); 284 } 285 else 286 printf("\n%s:%d的文件传送失败\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port)); 287 fclose(fp); 288 rename("data",file.md5);//这里可以修改文件的名字 289 exit(0); 290 break; 291 } 292 case FILE_PULL: 293 { 294 break; 295 } 296 case FILE_LIST: 297 { 298 break; 299 } 300 case FILE_DELECT: 301 { 302 break; 303 } 304 default: 305 { 306 break; 307 } 308 } 309 close(clientfd);//短连接结束 310 exit(0);//退出子进程 311 } 312 } 313 314 return 0; 315 } 316 317 318 //函数定义 319 int mysql_check_login(struct User user) 320 {... ...
377 } 378 ... ...
复制代码

   上面已经介绍了如何计算MD5值并写入数据库,接下来要做的事就是如何判断要上传的文件是否在服务器中已经存在,如果存在就可以不用上传,而是在relations表中记录,写入uid-fid关系,这样就可以实现网盘的秒传功能了。而如何区分文件是否相同,我这里使用的是以MD5作为文件指纹。话说秒传功能也不过如此吧。所以现在应该知道为什么有的文件可以秒传,有的不可以了吧。关于具体的解释可以参考杜鑫先生在知乎中的回到。传送门在第一小节中有。

  已加入验证和秒传功能的网盘程序

  client.cpp修改如下

复制代码
     ... ... 
188 int file_push(struct Addr addr,struct User user,char *filenames)
189 {... ...
238 //发送文件指纹 239 strcpy(file.filename,filenames); 240 strcpy(file.md5,md5); 241 file.uid=user.uid; 242 if(send(sockfd,(char *)&file,sizeof(struct File),0)<0) 243 { 244 perror("文件指纹发送失败"); 245 exit(-1); 246 } 247 char ch[64]; 248 if(recv(sockfd,ch,64,0)<0) 249 { 250 perror("error"); 251 } 252 if(ch[0]=='y')//表示已经存在 253 { 254 printf("该文件在服务器中存在,正使用秒传功能。\n"); 255 printf("传输完毕\n"); 256 return 0; 257 } 258 //打开文件 259 if((fp=fopen(filenames,"rb"))==NULL) 260 { 261 perror("文件打开失败"); 262 exit(-1); 263 } 264 char buffer[BUFFER_SIZE]; 265 bzero(buffer,BUFFER_SIZE); 266 printf("正在传输文件"); 267 int len=0; 268 //不断的读取文件直到文件结束 269 while((len=fread(buffer,1,BUFFER_SIZE,fp))>0) 270 { 271 if(send(sockfd,buffer,len,0)<0) 272 { 273 perror("发送数据失败"); 274 exit(-1); 275 } 276 bzero(buffer,BUFFER_SIZE); 277 printf(".");//1K打印一个点//如果要实现百分比,就要计算文件大小,然后再处理即可 278 } 279 280 printf("传输完毕\n"); 281 fclose(fp);//关闭文件流 282 close(sockfd);//关闭socket连接 283 284 return 0; 285 } 286 ... ...
复制代码

  server.cpp修改如下

复制代码
      ......
 61 int main(int argc,char *argv[])
 62 {......
110         //来一个连接就创建一个进程进行处理
111         pid=fork();
112         if(pid<0)
113         {
114             perror("fork error");
115         }
116         else if(pid==0)
117         {
118             recv(clientfd,(char *)&control,sizeof(struct Control),0);
119             printf("用户 %d 使用命令 %d\n",control.uid,control.control);
120             switch(control.control)
121             {
122                 case USER_CHECK_LOGIN:... ...
138 case FILE_PUSH: 139 { 140 char buffer[BUFFER_SIZE]; 141 int data_len; 142 FILE * fp=NULL; 143 struct File file; 144 //获取文件指纹 145 recv(clientfd,(char *)&file,sizeof(struct File),0); 146 printf("获取到的用户名ID: %d 文件名:%s MD5:%s\n",file.uid,file.filename,file.md5); 147 //对文件进行验证,如果文件已经存在就不用进行接收了 148 int t=mysql_check_md5(file); 149 char ch[64]={0}; 150 printf("t=%d\n",t); 151 if(t!=0) 152 { 153 printf("该文件存在,使用秒传功能\n"); 154 strcpy(ch,"yes"); 155 send(clientfd,ch,64,0); 156 mysql_file_in(file.uid,t); 157 continue; 158 } 159 strcpy(ch,"no"); 160 send(clientfd,ch,64,0); 161 printf("md5验证后得到的fid:%d\n",t); 162 bzero(buffer,BUFFER_SIZE);... ... ...
202 break; 203 }... ...
220 } 221 close(clientfd);//短连接结束 222 exit(0);//退出子进程 223 } 224 } 225 226 return 0; 227 } 228 229 230 //函数定义 231 int mysql_check_md5(struct File file) 232 { 233 MYSQL conn; 234 MYSQL_RES * res_ptr; 235 MYSQL_ROW result_row; 236 int res;int row;int column;int value=0; 237 char sql[256]={0}; 238 strcpy(sql,"select fid from files where md5='"); 239 strcat(sql,file.md5); 240 strcat(sql,"';"); 241 printf("查询的sql:%s\n",sql); 242 243 mysql_init(&conn); 244 if(mysql_real_connect(&conn,"localhost","root","","filetranslate",0,NULL,CLIENT_FOUND_ROWS)) 245 { 246 res=mysql_query(&conn,sql); 247 if(res) 248 { 249 perror("Select Sql Error!"); 250 exit(-1); 251 } 252 else 253 { 254 res_ptr=mysql_store_result(&conn); 255 if(res_ptr) 256 { 257 column=mysql_num_fields(res_ptr); 258 row=mysql_num_rows(res_ptr)+1; 259 if(row<=1) 260 { 261 ; 262 } 263 else 264 { 265 result_row=mysql_fetch_row(res_ptr); 266 value=atoi(result_row[0]); 267 } 268 } 269 else 270 { 271 printf("没有查询到匹配的数据\n"); 272 } 273 } 274 } 275 else 276 { 277 perror("Connect Failed!"); 278 exit(-1); 279 } 280 mysql_close(&conn); 281 return value;//返回fid 282 } 283 284 int mysql_file_in(int uid,int fid) 285 { 286 MYSQL conn; 287 int res; 288 char sql[256]; 289 char tmp[32]; 290 mysql_init(&conn); 291 if(mysql_real_connect(&conn,"localhost","root","","filetranslate",0,NULL,CLIENT_FOUND_ROWS)) 292 { 293 //insert into files values(uid,fid); 294 memset(sql,0,sizeof(sql)); 295 strcpy(sql,"insert into relations values("); 296 sprintf(tmp,"%d",uid); 297 strcat(sql,tmp); 298 strcat(sql,","); 299 sprintf(tmp,"%d",fid); 300 strcat(sql,tmp); 301 strcat(sql,");"); 302 printf("插入的sql语句: %s\n",sql); 303 res=mysql_query(&conn,sql); 304 if(res) 305 printf("Insert Error!\n"); 306 else 307 printf("Insert Success!\n"); 308 } 309 else 310 { 311 perror("Connect Failed!"); 312 exit(-1); 313 } 314 return 0; 315 } 316 ... ...
复制代码

   运行时的截图

   由上图可以看出如果该文件在服务器中存在的话,那么下一次上传同一个文件的话就会跳过上传的步骤,而是把数据库中的标识号给用户uid即可。具体关系可以看下面数据库数据。

  好了,现在的上传功能已经很完善了。下一节将实现下载功能了。

 

  本文地址: http://www.cnblogs.com/wunaozai/p/3891062.html


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384130.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LInux下du, df, top, free, pstack, su, sudo, adduser, password命令

1.du命令&#xff1a;du [选项] 文件 (1)功能该命令是显示指定文件以及下的所有文件占用系统数据块的情况&#xff0c;如果没有文件&#xff0c;默认为是当前工作目录 -a    显示所有文件对系统数据块的使用情况 -b    显示数据块大小时以字节为基本单位 -c    除了显…

HDU - 5919 Sequence II——主席树+区间种类++逆序建树

【题目描述】 HDU - 5919 Sequence II 【题目分析】 题目给定一个数组&#xff0c;每次查询一个区间&#xff0c;找出区间内不同数字的个数x&#xff0c;然后输出按出现顺序第x/2向上取整个数字的位置。 按照要求&#xff0c;我们首先需要能够找出给定区间不同的数字个数。 首…

Socket网络编程--小小网盘程序(4)

http://www.cnblogs.com/wunaozai/p/3892729.html 在这一小节中实现了文件的下载&#xff0c;具体的思路是根据用户的uid和用户提供的文件名filename联合两张表&#xff0c;取得md5唯一标识符&#xff0c;然后操作这个标识符对应的文件发送给客户端。 实现下载的小小网盘程序 …

静态顺序表的实现

实现对顺序表的初始化&#xff0c;头插&#xff0c;头删&#xff0c;尾插&#xff0c;尾删&#xff0c; 任意下标的删除&#xff0c; 任意下标处的的元素删除&#xff0c;任意下标处的元素插入&#xff0c;任意元素的下标返回&#xff0c;任意下标处的元素返回&#xff0c; 删除…

树链剖分入门+HYSBZ - 1036树的统计Count

今天学习了树链剖分&#xff0c;记录一下。 【题目背景】 HYSBZ - 1036树的统计Count 【题目分析】 题目要求求任意结点之间路径的和以及路径上最大的结点&#xff0c;还有可能修改。如果正常做可能会很复杂&#xff08;我也不知道正常应该怎么做&#xff0c;应该要用到LCA什么…

Socket网络编程--小小网盘程序(5)

http://www.cnblogs.com/wunaozai/p/3893469.html 各位好呀&#xff01;这一小节应该就是这个小小网盘程序的最后一小节了&#xff0c;这一节将实现最后的三个功能&#xff0c;即列出用户在服务器中的文件列表&#xff0c;还有删除用户在服务器中的文件&#xff0c;最后的可以共…

进程相关概念

1.进程相关概念 进程是代码的一次动态执行&#xff0c;担当分配系统资源的角色&#xff0c;进程信息是被放在一个一个数据结构中&#xff0c;是一个结构体task_struct 2.进程控制块内容 //linux下的进程控制块 struct task_struct {volatile long state;// 说明了该进程是否可以…

SPOJ - QTREE3Query on a tree again!——树链剖分

【题目描述】 SPOJ - QTREE3Query on a tree again! 【题目分析】 题目要求是输出从111到xxx的路径上遇到的第一个黑色的点。我们可以用树链剖分&#xff08;不了解的同学请出门左拐&#xff0c;详见树链剖分入门&#xff09; 我们用线段树维护每个区间第一次遇到黑点的位置&a…

C++中的函数指针和函数对象总结

http://www.cnblogs.com/lvpengms/archive/2011/02/21/1960078.html 篇一、函数指针 函数指针&#xff1a;是指向函数的指针变量&#xff0c;在C编译时&#xff0c;每一个函数都有一个入口地址&#xff0c;那么这个指向这个函数的函数指针便指向这个地址。 函数指针的用途是很…

开发工具

1.编辑器 &#xff08;1&#xff09;vim     vim是从vi发展出来的一个文本编辑器。代码补完、编译错误跳转等方便编程的功能特别丰富&#xff0c;在程序员中被广泛使用。 &#xff08;2&#xff09;sed     sed是一种流编辑器&#xff0c;它一次处理一行内容。处理时…

c++ 智能指针用法详解

http://www.cnblogs.com/TenosDoIt/p/3456704.html 本文介绍c里面的四个智能指针: auto_ptr, shared_ptr, weak_ptr, unique_ptr 其中后三个是c11支持&#xff0c;并且第一个已经被c11弃用。 为什么要使用智能指针&#xff1a;我们知道c的内存管理是让很多人头疼的事&#xff0…

CodeForces - 786BLegacy——线段树建图+最短路

【题目描述】 CodeForces - 786BLegacy 【题目分析】 题目大概意思就是有三种操作&#xff1a; 从某个点到另一个点从某个点到另一个区间从某个区间到另一个点 然后询问从其中一个点到其他所有点的距离——这很显然是一个求单源最短路径的。我们简单的想法显然是建一个图&a…

自主编写shell

1.替换原理 用fork创建子进程后执行的是和父进程相同的程序&#xff08;但有可能执行不同的代码分支&#xff09;&#xff0c;子进程往往要调用一种exec函数以执行例外一个程序。当进程调用一种exec函数时&#xff0c;该进程的用户空间代码和数据完全被新程序替换&#xff0c;从…

HYSBZ - 2243染色——树链剖分+线段树建树技巧

【题目描述】 HYSBZ - 2243染色 【题目分析】 我一直没有看清楚题&#xff0c;以为求的是路径上出现颜色的种类&#xff0c;然后就写了一个区间染色的线段树进行维护&#xff0c;过样例的时候才发现题读错了&#xff0c;人家要求的是路径上出现的颜色段&#xff0c;所以颜色的…

打动态库和静态库

一.动态库和静态库的定义 1.静态库     程序在编译链接时把库的代码链接到可执行文件中。程序运行时就不再需要静态库 2.动态库     程序在运行的时候才去链接动态库的代码&#xff0c;多个程序 共享使用代码 3.动态链接     在执行文件之前&#xff0c;外部…

HYSBZ - 2157树链剖分

【题目描述】 HYSBZ - 2157树链剖分 【题目分析】 这道题给出的是边权而不是点权&#xff0c;但是我们分析这个树就会发现每个节点都只有一个父亲&#xff0c;也就是每条边的边权都可以存放在儿子节点上&#xff0c;然后在遍历路径的时候我们在从前往后遍历&#xff0c;但是注…

C++11中的右值引用

http://www.cnblogs.com/yanqi0124/p/4723698.html 在C98中有左值和右值的概念&#xff0c;不过这两个概念对于很多程序员并不关心&#xff0c;因为不知道这两个概念照样可以写出好程序。在C11中对右值的概念进行了增强&#xff0c;我个人理解这部分内容是C11引入的特性中最难以…

BZOJ2115XOR——线性基

【题目描述】 BZOJ2115XOR——线性基 【题目分析】 这道题看完以后很懵逼&#xff0c;人家要是走的很复杂呢&#xff1f;各种绕来绕去怎么办&#xff1f; 首先我们应该注意到一个很明显的道理&#xff1a;重复的路径会和自身抵消&#xff0c;所以我们大可以随便跑&#xff0c;…

单链表的相关操作

1.冒泡排序对单链表进行排序 void LinkListBubbleSort(LinkNode* head) {if(head NULL){ return;//空链表} if(head -> next NULL){ return;//只有一个结点} LinkNode* cur head;//趟数LinkNode* tail NULL;//尾指针LinkNode* tmp head;//次数for(; cur -…

socket网络编程--epoll小结

http://www.cnblogs.com/wunaozai/p/3895860.html 以前使用的用于I/O多路复用为了方便就使用select函数&#xff0c;但select这个函数是有缺陷的。因为它所支持的并发连接数是有限的(一般小于1024)&#xff0c;因为用户处理的数组是使用硬编码的。这个最大值为FD_SETSIZE&#…