网络编程实用教程第二版_第2章.pptVIP

  • 0
  • 0
  • 约1.18万字
  • 约 100页
  • 2019-09-10 发布于辽宁
  • 举报
memset( (char*) servaddr, 0, sizeof(servaddr) ); /* 清空sockaddr结构 */ servaddr.sin_family = AF_INET; /* 设置为因特网协议族 */ servaddr.sin_addr.s_addr = INADDR_ANY; /* 设置本地IP地址 */ ? /* 检查命令行参数,如果指定了,就是用该端口号,否则使用缺省端口号 */ if (argc 1){ port = atoi(argv[1]); /* 如果指定了端口号,就将它转换成整数 */ } else { port = PROTOPORT; /* 否则,使用缺省端口号 */ } if (port 0) /* 测试端口号是否合法 */ servaddr.sin_port=htons( (u_short)port ); else{ /* 打印错误信息并退出 */ fprintf( stderr, ”bad port number %s\n”, argv[1] ); exit(1); } ? /* 创建一个用于监听的流式套接字 */ listenfd = SOCKET(AF_INET,SOCK_STREAM,0); if (listenfd 0) { fprintf( stderr, “socket creation failed\n” ); exit(1); } /* 将本地地址绑定到监听套接字*/ if ( bind( listenfd, (struct sockaddr *) servaddr, sizeof(servaddr)) 0) { fprintf(stderr, ”bind failed\n” ); exit(1); } ? /* 开始监听,并指定监听套接字请求队列的长度 */ if (listen(listenfd, QLEN) 0) { fprintf(stderr, ”listen filed\n” ); exit(1); } /* 服务器主循环—接受和处理来自客户端的连接请求 */ while(1) { alen = sizeof(clientaddr); /* 接受客户端连接请求,并生成响应套接字 */ if((clientfd = accept( listenfd, (struct sockaddr *) clientaddr, alen)) 0 ) { fprintf( stderr, “accept failed\n”); exit(1); } visits++; /* 累加访问的客户数 */ sprintf( buf, “this server has been contacted %d time \n”, visits ); send(clientfd, buf, strlen(buf), 0 ); /* 向客户端发送信息 */ closesocket( clientfd ); /* 关闭响应套接字 */ } } 关于阻塞的问题 图2.7 服务器进程因调用ACCEPT()而被阻塞 2.3.4 进程的阻塞问题和对策 1.什么是阻塞 阻塞是指一个进程执行了一个函数或者系统调用,该函数由于某种原因不能立即完成,因而不能返回调用它的进程,导致进程受控于这个函数而处于等待的状态,进程的这种状态称为阻塞。 图2.8 RECV()函数的两种执行方式 2.能引起阻塞的套接字调用 在Berkeley套接字网络编程接口的模型中,套接字的默认行为是阻塞的,具体地说,在一定情况下,有多个操作套接字的系统调用会引起进程阻塞。 (1)ACCEPT() (2)READ()、RECV()和READFORM() (3)WRITE()、SEND()和SENDTO() (4)CONNECT() (5)SELECT() (6)CLOSESOCKET() 3.阻塞工作模式带来的问题 采用阻塞工作模式的单进程服务器是不能很好地同时为多个客户服务的。 图2.9是一个例子。 图2.9 采用阻塞工作模式的服务器不能很好地为多个客户服务 4.一种解决方案 利用UNIX操作系统的FORK()系统调用,编制多进程并发执行的服务器程序。可以创建子进程。对于每一个客户端,用一个专门的进程为它服务,通过进程的并发执行,来实现对多个客户的并发服务。基本的编程框架是:

文档评论(0)

1亿VIP精品文档

相关文档