综合实验报告聊天室的

时间:2024.4.30

华北科技学院计算机学院综合性实验

实 验 报 告

课程名称 ASP.NET程序设计

实验学期 2013 至 2014 学年 第 一 学期

学生所在系部 管理学院

年级 11级 专业班级 电商B112

学生姓名 赵世明 学号 201104064223 任课教师 崔新伟

实验成绩

计算机学院制

华北科技学院计算机学院综合性实验报告

《ASP.NET程序设计》课程综合性实验报告

综合实验报告聊天室的

第 1 页

综合实验报告聊天室的

第 2 页

综合实验报告聊天室的

综合实验报告聊天室的

第 3 页

综合实验报告聊天室的

第 4 页

综合实验报告聊天室的

综合实验报告聊天室的

第 5 页

综合实验报告聊天室的

第 6 页

综合实验报告聊天室的

第 7 页

综合实验报告聊天室的

第 8 页

综合实验报告聊天室的

第 9 页


第二篇:这个程序是一个综合的聊天室服务器


/*这个程序是一个综合的聊天室服务器

* 这个版本的程序就可以处理 服务器端的标准输入,也能同时处理客户端的读写了 * 每个客户链接到来,fork一个子进程进行处理。子进程之间的通讯主要采用共享内存 *对各种信号作出反应,主要信号有 sigchld,sigterm,siginter,

*

* */

#include"head.h"

#define MAX_USER 1024

#define MAX_PROCESS 65535

#define BUF_SIZE 1024

#define MAX_EVENT_NUMBER 1024

#define USER_LIMIT 65535

typedef struct user

{

int conn;

int stop;

int pipefd[2];

int user_number;

sockaddr_in client_addr;

char bufread[BUF_SIZE];

char bufwrite[BUF_SIZE];

pid_t pid; // which process deal with this user

} user;

typedef struct subprocessData

{

user* u;

pid_t pid;

pid_t ppid;

}subprocessData;

subprocessData subprocess[MAX_PROCESS];

static const char* shm_name="/mysharememory";

char * share_mem=0;

int shmfd;

int sig_pipefd[2];

int user_number=0;

/* 当sigchld信号发生时,调用这个函数来处理该信号*/

void sig_handler(int sig)

{

int save_errno=errno;

int msg=sig;

send(sig_pipefd[1],(char*)&msg,sizeof(msg),0);

errno=save_errno;

}

/*具体用来处理信号事件的函数*/

void sig_concrete_handler(int sig,int epollfd)

{

printf("signal chld occur\n");

pid_t pid;

int stat_loc;

while(pid=waitpid(-1,&stat_loc,WNOHANG)>0)

//pid=waitpid(-1,&stat_loc,WNOHANG)>0;

if(pid>0)

{

/*作一些具体的回收工作,比如关闭子进程中打开的socket,但是,我们目前无法直接获得该socket,无法关闭;只能获取目前的子进程的pid,所以,需要建立pid与连接socket之间的联系,可以用一个简单的数组作对应。也可以用一个结构体(记录多种数据)+一个全局化的数组来作对应,这里用subprocess将pid于user对应*/

printf("close process %d\n",pid);

subprocess[pid].u->stop=1;

subprocess[pid].u->pid=-1;

//不再监听与父进程通信的管道了

epoll_ctl(epollfd,EPOLL_CTL_DEL,subprocess[pid].u->pipefd[0],0); //关闭与父进程通信的管道了

close(subprocess[pid].u->pipefd[0]);

//关闭与客户端的连接

close(subprocess[pid].u->conn);

}

}

/*添加对信号的处理,先对sigchld进行处理*/

int add_sig(int signum, void(handler)(int) )

{

struct sigaction sa;

memset(&sa,'\0',sizeof(sa));

sa.sa_handler=handler;

sa.sa_flags|=SA_RESTART;

//这个的意思是将所有的信号都监听,然后都是调用一个handler来处理。这样看上去好像不太合理。但是,后面我们就知道,为了统一事件源,在此将所有信号一视同仁的处理,在接下来的IO复用中,会有好处的。

sigfillset(&sa.sa_mask);

assert(sigaction(signum,&sa,NULL)!=-1);

}

int dowork(user curuser)

{

setnonblock(curuser.conn);

// while(!curuser.stop )

{

int readn=read(curuser.conn,curuser.bufread,BUF_SIZE);

if( (readn<0) && (errno!=EAGAIN))

{

printf("a\n");

printf("read fail, client %d\n",curuser.conn);

close(curuser.conn);

curuser.conn=-1;

curuser.stop=1;

}

else if (readn==0)

{

printf("b\n");

close(curuser.conn);

curuser.conn=-1;

curuser.stop=1;

}

else if (readn>0)

{

printf("pid= %d\n",getpid());

curuser.bufread[readn]='\0';

memcpy(curuser.bufwrite,curuser.bufread,sizeof(curuser.bufread));

int writen=write(curuser.conn,curuser.bufwrite,sizeof(curuser.bufwrite));

memset(curuser.bufread,0,sizeof(curuser.bufread));

printf("write %d bytes to %d\n",writen,curuser.conn);

}

}

}

int maxfd(int * allsockets,int num)

{

}

int addfd(int epollfd, int fd)

{

epoll_event event;

event.data.fd=fd;

//event.events=EPOLLIN|EPOLLET;

event.events=EPOLLIN;

epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&event);

setnonblock(fd);

}

int runchild(user* curuser,char *shmem)

{

assert(curuser!=NULL);

int child_epollfd=epoll_create(5);

assert(child_epollfd!=-1);

epoll_event events[MAX_EVENT_NUMBER];

int conn=curuser->conn;

addfd(child_epollfd,conn);

addfd(child_epollfd,curuser->pipefd[1]);

int stop_child=0;

int ret=0;

while(!stop_child)

{

printf("in child\n");

int number=epoll_wait(child_epollfd,events,MAX_EVENT_NUMBER,-1); if(number<0 && errno!=EINTR)

{

printf("epoll error in child");

break;

}

for(int i=0;i<number;i++)

{

int sockfd=events[i].data.fd;

if(sockfd ==conn && (events[i].events & EPOLLIN) )

{

memset(shmem+curuser->user_number*BUF_SIZE,'\0',BUF_SIZE);

ret=recv(conn,shmem+curuser->user_number*BUF_SIZE,BUF_SIZE-1,0);

if(ret<0 && errno!=EAGAIN)

stop_child=1;

else if (ret==0)

stop_child=1;

else

//通知父进程,有了数据啦,让父进程告诉别的子进程去读吧。哈哈

{

shmem[curuser->user_number*BUF_SIZE+ret]='\0';

printf("some thing\n");

send(curuser->pipefd[1],(char*)&(curuser->user_number),sizeof(curuser->user_number),0);

}

}

else if (sockfd==curuser->pipefd[1] && events[i].events & EPOLLIN)

{

printf("some thing from father\n");

int client_number;

ret=recv(sockfd,(char*)&client_number,sizeof(client_number),0);

if(ret<0 && errno!=EAGAIN)

{

stop_child=1;

}

else if (ret==0)

stop_child=1;

else

//从收到的客户端那里读取内容,往自己这里写 {

// printf("rec from father,then write to his client\n");

char tmpbuf[BUF_SIZE*2];

sprintf(tmpbuf,"client %d says: ",client_number);

//memcpy(tmpbuf+sizeof(tmpbuf),shmem+(client_number)*BUF_SIZE,BUF_SIZE);

sprintf(tmpbuf+15,"%s",shmem+(client_number*BUF_SIZE));

// send(conn,tmpbuf,sizeof(tmpbuf),0); send(conn,tmpbuf,strlen(tmpbuf),0);

}

}

}

}

}

int main(int argc, char **argv)

{

if(argc<3)

{

printf("usage: %s ip port\n",basename(argv[0]));

exit(0);

}

printf("start echoback server...\n");

char * ip=(char * ) argv[1];

int port =atoi(argv[2]);

/*构造服务器端的地址,主要是填充sockaddr_in 结构体*/

struct sockaddr_in server_address;

bzero(&server_address,sizeof(server_address));

server_address.sin_family=AF_INET;

inet_pton(AF_INET,ip,&server_address.sin_addr);

server_address.sin_port=htons(port);

int listenfd=socket(AF_INET,SOCK_STREAM,0);

assert(listenfd>=0);

int reuse=1;

setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)); // setnonblock(listenfd);

int bindret=bind(listenfd,(struct sockaddr *) &server_address, sizeof(server_address)); assert(bindret==0);

bindret=listen(listenfd,5);

assert(bindret==0);

/*deal with epoll*/

epoll_event events [ MAX_EVENT_NUMBER];

int epollfd=epoll_create(5);

assert(epollfd!=-1);

//注册listenfd上的可读事件

addfd(epollfd,listenfd);

//注册标准输入上的可读事件

addfd(epollfd,0);

//用来作为信号与epoll链接的管道

int retsigpipe=socketpair(AF_UNIX,SOCK_STREAM,0,sig_pipefd);

addfd(epollfd,sig_pipefd[0]);

add_sig(SIGCHLD,sig_handler);

add_sig(SIGTERM,sig_handler);

add_sig(SIGINT,sig_handler);

/*服务器服务启动,等待客户端的链接的到来*/

int run_flag=1;

user users[MAX_USER];

for(int i=0;i<MAX_USER;i++)

users[i].conn=-1; // 用-1 表示目前这个conn可用

//time out

struct timeval timeout;

timeout.tv_sec=0;

timeout.tv_usec=100;

//deal with 标准输入

char ioinput[1024];

//创建共享内存

//开辟一块内存,返回一个共享内存对象

shmfd=shm_open(shm_name,O_CREAT|O_RDWR,0666);

assert(shmfd!=-1);

//将这个共享内存对象的大小设定为 **

int ret=ftruncate(shmfd,USER_LIMIT*BUF_SIZE);

assert(ret!=-1);

//将刚才开辟的共享内存,关联到调用进程

share_mem=(char *) mmap(NULL,USER_LIMIT*BUF_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED,shmfd,0);

assert(share_mem!=MAP_FAILED);

while(run_flag)

{

int number=epoll_wait(epollfd,events,MAX_EVENT_NUMBER,-1);

if(number<0 && errno !=EINTR)

{

perror(0);

printf("epoll error\n");

break;

}

for(int i=0;i<number;i++)

{

int sockfd=events[i].data.fd;

if(sockfd==listenfd)

{

int acfd=accept(listenfd,NULL,NULL);

if(acfd>=0)

{

printf("yes\n");

user_number++;

/*users[user_number] 表示一个conn,唯一标识这个用户链接*/

users[user_number].conn=acfd;

users[user_number].user_number=user_number;

//父子进程间的管道

int

piperet=socketpair(AF_UNIX,SOCK_STREAM,0,users[user_number].pipefd);

assert(piperet==0);

pid_t pid=fork();

//此时,我们创建一个子进程,专门负责这个客户端的一切事物

//为了方便知道哪个子进程的事件,我们用conn作为索引,即将之视为主键,对进程和链接进行索引和对照

if(pid<0)

{

printf("fork error\n");

break;

}

else if(pid==0) //子进程中,处理一切事物

{

close(listenfd);

close(users[user_number].pipefd[0]); close(epollfd);

printf("run child\n");

runchild(&(users[user_number]),share_mem);

munmap((void*)share_mem,USER_LIMIT*BUF_SIZE);

exit(0);

}

else

{

//close(users[user_number].conn);

close(acfd);

close(users[user_number].pipefd[1]);

addfd(epollfd,users[user_number].pipefd[0]); users[user_number].pid=pid;

subprocess[pid].u=&users[user_number];

}

}

else

{

printf("accept error\n");

break;

}

}

else if (sockfd==0)

{

scanf("%s",ioinput);

printf("%s\n",ioinput);

}

else if (sockfd ==sig_pipefd[0])

{

int sig_numbers[1024];

int resig=recv(events[i].data.fd, sig_numbers,1024,0);

if(resig<0 )

continue;

else if (resig==0)

continue;

else

{

for(int k=0;k<resig;k++)

{

switch(sig_numbers[k])

{

case SIGCHLD:

{

//to do . a concrete function

sig_concrete_handler(SIGCHLD,epollfd);

}

case SIGTERM:

case SIGINT:

{

for(int

w=0;w<user_number;w++)

{

int

pid_to_kill=users[user_number].pid;

kill(pid_to_kill,SIGTERM);

}

run_flag=0;

break;

}

default:

{

break;

}

}

}

}

}

else // 说明是某个表示客户链接的套接字有内容需要读 {

printf("is here?\n");

int client_number;

int re=recv(events[i].data.fd, &client_number,sizeof(client_number),0);

if(re<0 && errno!=EAGAIN)

run_flag=0;

else if (re==0)

run_flag=0;

else

{

for(int j=0;j<=user_number;j++)

{

if(users[j].pipefd[0]!=events[i].data.fd) {

send(users[j].pipefd[0],(char*)&client_number,sizeof(client_number),0);

}

}

}

} }

}

}

更多相关推荐:
综合实验报告

内蒙古科技大学本科生材料综合实验报告题目热轧Q345钢10压下率空冷和水冷后的组织和硬度的分析报告专业材料成型及控制工程班级成型106班学号姓名指导老师1内蒙古科技大学本科生综合实验目录一实验目的错误未定义书签...

综合实验实验报告

综合实验实验报告安息香的辅酶合成及其转化班级轻化1101姓名童飞昀汪娇学号实验名称安息香的辅酶合成及其转化实验目的1学习安息香缩合反应及安息香转化的基本原理2学习以维生素B1为催化剂合成安息香的实验原理和操作过...

大综合实验报告

信号波形分离及合成大综合电路设计题目一课题的任务课题任务对一个特定频率的方波进行变换产生3个不同频率的正弦信号再将这些正弦信号合成为近似方波电路方框图图1课题参考实现方案要求16人7人为一个小组请各班课代表将组...

综合实验报告样本

专业综合实验报告宋体一号加粗居中请注意行距的区别实验项目名称所属课程名称专业综合实验学生姓名学号专业宋体小三加粗居中20xxXXXX西安工业大学综合实验报告实验题目宋体三号加粗居中摘要小三号宋体加粗居中小四宋体...

综合实验报告

综合实验报告书20xx20xx学年实验题目粒毛盘菌胞外多糖的提取及其脱蛋白前后抗氧化活性学院名称生物与食品工程学院专业班级生物工程101班姓名学号郑沛20xx6274起讫日期20xx年2月25日20xx年3月1...

综合实验报告

化学综合实验第十组1班120xx901211班120xx90120环境工程1班120xx90130环境工程1班120xx90131祝钰朱丽华林斌刘刚组长环境工程组员环境工程甲基橙的制备及性能测定一实验目的1掌握...

c语言综合实验报告

计算机系综合性实验实验报告课程名称程序设计语言C实验学期20xx至20xx学年第二学期学生所在系部年级专业班级学生姓名学号任课教师实验成绩计算机系制计算机系综合性实验报告实验报告须知1学生上交实验报告时必须为打...

C程序设计综合实验报告

华北科技学院计算机系综合性实验实验报告课程名称C程序设计实验学期20xx至20xx学年第二学期学生所在系部年级专业班级学生姓名学号任课教师孙改平实验成绩计算机系制华北科技学院计算机系综合性实验报告C程序设计课程...

测控专业 综合实验报告

湖南科技大学测控技术与仪器专业专业综合实验报告姓名学号成绩湖南科技大学机电工程学院二一三年十一月十一日目录一液压泵站综合控制实验3一实验目的3二实验内容3二液压实验台PLC控制实验4一实验目的4二实验内容4三振...

Java综合实验报告模板

华北科技学院计算机学院综合性实验实验报告课程名称面向对象程序设计Java实验学期20xx至20xx学年第一学期学生所在院部计算机学院年级20xx专业班级软件B12X学生姓名XXX学号20xx0XXXXXXX任课...

SQL综合实验报告范本

华北科技学院计算机系综合性实验实验报告课程名称SQLSERVER数据库设计实验学期20xx至20xx学年第1学期学生所在系部计算机系年级08级专业班级计算机应用技术学生姓名王二斌学号20xx07013111任课...

综合性实验报告1

重庆交通大学信息科学与工程学院综合性实验报告姓名学号班级通信工程专业20xx级3班实验项目名称DFT变换的性质及应用实验项目性质综合性实验实验所属课程数字信号处理实验室中心软件实验中心指导教师张颖实验完成时间2...

综合实验报告(37篇)