信息安全实践第九次作业 并发服务器III——多路IO模型_第1页
信息安全实践第九次作业 并发服务器III——多路IO模型_第2页
信息安全实践第九次作业 并发服务器III——多路IO模型_第3页
信息安全实践第九次作业 并发服务器III——多路IO模型_第4页
信息安全实践第九次作业 并发服务器III——多路IO模型_第5页
已阅读5页,还剩17页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

四 川 大 学 计 算 机 学 院、软 件 学 院实 验 报 告 学号:姓名:专业:_软件工程_ 班级: 第 9 周 课程名称 信息安全产品开发实践 实验课时4实验项目并发服务器III多路I/O模型实验时间2013.11.9实验目的 利用select函数实现在Linux环境下实现一个聊天室程序 实验环境 虚拟机 Ubuntu-VMware Workstation 实验内容(算法、程序、步骤和方法) 这次的实验还是分服务器和客户端,客户端的代码基本用demo中的就行了,只需把通过输入exit退出改成通过输入/quit退出就行了。服务器有关多路I/O的核心代码已经在demo中完成了,理论上只需要往demo程序中添加聊天室的各个功能就好了。但是个人刚开始对demo服务器代码还是有疑问,所以把demo程序的一部分代码修改过,主要改动如下:1、 在扫描所有文件描述符的for循环中,demo程序是从sockfd(广播时+1)服务器套接字(文件描述符)开始往后扫描的,我把它改成了从0(或3)开始扫描(当然,这样做的话需要注意在广播的时候要跳过sockfd)。2、 在demo程序中接收新用户是clientinfonewfd.client_id = newfd,而clientinfo的长度为BACKLOG 10,先不说文件描述符0、1、2分别代表着标准输入、标准输出、标准错误输出,实际能用的只有7个,而且也不能保证新建的套接字(文件描述符)数值不超过9,所以我把demo改成当接收新用户时用一个for循环在clientinfo中寻找空闲结点(空闲结点里面的client_id为-1),结点下标和文件描述符本身并没关系(当然也可以把BACKLOG定义为FD_SETSIZE)。不过有关这两点改动在后来的试验中发现时毫无意义的,因为文件描述符是从3开始往上递增建立,就是说sockfd作为第一个建立的文件描述符数值为3(所有套接字中最小),后面建立的套接字会按加1递增。接下来的就是一些细节问题了,如:1、 接收username的时候要注意把最后的换行符n改成0。2、 使用strcmp判断对方的命令的时候不能在第二个参数中直接放一个字符串常量(如strcmp(data_buf, /help),要另外声明一个字符指针变量。3、 .以下是代码:/*linux-socket-select-异步聊天室talk_server.cwrited by hanzhongqiu 13/04/2009Using select() for I/O multiplexing */#include #include #include #include #include #include #include /* port were listening on */#define SERVERPORT 1573/*maximum cnnnect number*/#define BACKLOG 10/*maximum data buffer*/#define BUFSIZE 2048struct client_infoint client_id;struct sockaddr_in client_address;char usrname256;/客户的名字int first;/用于只是用户是否刚刚登陆;int main()/*master file descriptor list*/fd_set master_fds;/*temple file descriptor list for select()*/fd_set read_fds;/*server address*/struct sockaddr_in server_addr;/*client address*/struct sockaddr_in client_addr;/*maximum file descriptor number*/int max_fd;/*listening socket file descriptor*/int sockfd;/*newly accept()ed socket file descreptor*/int newfd;/*buffer for saving client data*/char data_bufBUFSIZE;char send_bufBUFSIZE;/*number of client data*/int nbytes;/*for set socket option*/int opt;opt = SO_REUSEADDR; /*lenth of address*/int addr_len;/*for accept() to use*/int size;size = sizeof(struct sockaddr);/*temple varient*/int tmp_i, tmp_j;struct client_info clientinfoBACKLOG;int temp;/*clear the master and temple file descriptor*/FD_ZERO(&master_fds);FD_ZERO(&read_fds);memset(&data_buf, 0, BUFSIZE);memset(&send_buf, 0, BUFSIZE);/*create socket*/if (-1 = (sockfd = socket(AF_INET, SOCK_STREAM, 0)perror(create socket() error:);exit(1);/*set the socket*/ if (-1 = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt) perror(setsockopt() error:);exit(1); /*bind first config the socket then binding*/memset(&server_addr, 0, size);server_addr.sin_family = AF_INET;server_addr.sin_port = htons(SERVERPORT);server_addr.sin_addr.s_addr = htonl(INADDR_ANY);bzero(&(server_addr.sin_zero), 8);if (-1 = bind(sockfd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr)perror(bind() socket error:);exit(1);/*listen */if (-1 = listen(sockfd, BACKLOG)perror(listen() error:);exit(1);/*add sockfd to master set*/FD_SET(sockfd, &master_fds);/*keep track the max file descriptor*/max_fd = sockfd;printf(server is ok!n);for (temp = 0;temp BACKLOG;temp+)clientinfotemp.client_id = -1;clientinfotemp.first = -1;/刚登陆还没输入用户名/*loop*/while (1)read_fds = master_fds;if (-1= select(max_fd + 1, &read_fds, NULL, NULL, NULL)/select监视perror(select() error!n);exit(1);/*looking for data to read*/for (tmp_i = 0; tmp_i = max_fd; tmp_i+)/轮询所有描述符/*got connect*/if (FD_ISSET(tmp_i, &read_fds)/判断是服务器还是客户端套接字if (tmp_i = sockfd)/服务器套接字监听到新的客户端newfd = accept(sockfd, (struct sockaddr*)&client_addr, &size);/新套接字for (temp = 0;temp max_fd)max_fd = newfd;printf(Get the new connect from %sn, (char*)inet_ntoa(client_addr.sin_addr);else/接收到客户端发过来的信息/*get data from the client*/for (temp = 0;temp nbytes)perror(recv() error:);exit(1);else if(0 = strcmp(data_buf, cmd)/客户端结束连接printf(client: %s - %s exit!n, (char*)inet_ntoa(clientinfotemp.client_address.sin_addr),clientinfotemp.usrname);strcat(send_buf, (char*)inet_ntoa(clientinfotemp.client_address.sin_addr);strcat(send_buf, -);strcat(send_buf, clientinfotemp.usrname);strcat(send_buf, was exit!);FD_CLR(tmp_i, &master_fds);/清除描述符memset(clientinfotemp.usrname, 0, 256);/清空结构体以留给下一个用户memset(&clientinfotemp.client_address, 0, size);clientinfotemp.client_id = -1;clientinfotemp.first = 0;close(tmp_i);for (tmp_j = 0; tmp_j = max_fd; tmp_j+)/广播有客户端退出消息if (FD_ISSET(tmp_j, &master_fds) & tmp_j!=sockfd)if (-1 = write(tmp_j, send_buf, sizeof(send_buf)perror(send data error:);/ end forelse if (clientinfotemp.first=0)/刚登陆准备输入客户名char *p;p = strchr(data_buf,n);*p = 0;/消除用户名后面的换行符printf(the new user %s : %s n, (char*)inet_ntoa(clientinfotmp_i.client_address.sin_addr), data_buf);strcat(clientinfotemp.usrname, data_buf);/设置新用户名clientinfotemp.first = 1;/已非刚登陆else/已有用户名的用户发送信息char *cmd1 = /help;char *cmd2 = /who;char *cmd3 = /send;if (strcmp(data_buf, cmd1) = 0)/显示帮助信息strcat(send_buf, broadcast at usualn);strcat(send_buf, /help:helping informationn);strcat(send_buf, /quit:quit the chatn);strcat(send_buf, /who:get the online clientsn);strcat(send_buf, /send username message: send message to usernamen);if (-1 = write(tmp_i, send_buf, sizeof(send_buf)perror(send data error:);else if (strcmp(data_buf, cmd2) = 0)/显示在线用户for (temp = 0;temp BACKLOG;temp+)if (clientinfotemp.client_id != -1)strcat(send_buf, (char*)inet_ntoa(clientinfotemp.client_address.sin_addr);strcat(send_buf, -);strcat(send_buf, clientinfotemp.usrname);strcat(send_buf, n);/ end forif (-1 = write(tmp_i, send_buf, sizeof(send_buf)perror(send data error:);elsechar *delim= ;char data_buf2BUFSIZE;strcat(data_buf2, data_buf);/如果是广播的话data_buf还是会被strtok切分if(strcmp(strtok(data_buf, delim), cmd3) = 0)/向指定用户发送点到点消息strcat(send_buf, private chat from );strcat(send_buf, (char*)inet_ntoa(clientinfotemp.client_address.sin_addr);strcat(send_buf, -);strcat(send_buf, clientinfotemp.usrname);strcat(send_buf, : n);char *name = strtok(NULL, delim);strcat(send_buf, strtok(NULL, delim);/如果直接用下面的循环的话会在最前面多一个空格char *message;while (message = strtok(NULL, delim)/防止对话内容有空格strcat(send_buf, );strcat(send_buf, message);for (temp = 0;temp BACKLOG;temp+)/寻找被指定的用户if (strcmp(name, clientinfotemp.usrname) = 0)if (-1 = write(clientinfotemp.client_id, send_buf, sizeof(send_buf)perror(send data error:);break;if (temp = BACKLOG)/没有找到用户名memset(&send_buf, 0, BUFSIZE);strcat(send_buf, the username not existn);if (-1 = write(tmp_i, send_buf, sizeof(send_buf)perror(send data error:);else/广播strcat(send_buf, (char*)inet_ntoa(clientinfotemp.client_address.sin_addr);strcat(send_buf, -);strcat(send_buf, clientinfotemp.usrname);strcat(send_buf, said: n);strcat(send_buf, data_buf2);for (t

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论