服务器Select模型的实现
write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie
讨论新闻组及文件
select模型属于网络的I/O复用模型,比纯粹的阻塞I/O模型更具有实用性,因为可以同时等待多个描述字的就绪。
当年学习C/C++的时候,很少碰到底层以数字标示的描述字,只在写文件系统的去尝试各种情况,以获得最佳效率的时候实际尝试使用过一次,一直觉得那种open,write,read的文件操作方式,实在是比fopen一族函数还要低级的方式-_-!平时没有必要使用。但是等到网络编程的时候,才发现。。。。原来这么底层的东西,竟然也有一定的通用性,文件的描述字和网络的描述字竟然是一致的-_-!不管是谁设计的,还是挺佩服的。。。。。。
这里仅仅是为了学习Select模型而写的学习例子,作用是在服务器端输出连接上的客户端的IP(仅以数字形式),然后将客户端的IP以字符串的形式返回,客户端连接服务器,并接受由服务器端返回的IP地址,然后输出转换为字符串形式的IP地址和数字形式的IP地址,为了区别select到正确的不同listen套接字,这里用了不同的端口,并且不同的两个套接字响应时以echo 1,echo 2区别。功能是很简单的,仅仅用于学习,所以其中很多地方本来可以抽出来称为函数的,都贪简单,直接复制了(-_-!这里本来习惯想说Ctrl-C Ctrl-V的。。。但是发现自己实在Ubuntu下用vim复制的,好像和实际情况不符。。。。)
另外。。。。由于用的是《Unix Network Programming》一书,所以编程风格都变得有点像书中了。。。。服务器端全是自己写的,客户端代码由书中的daytime客户端改过来的,并且发现书中客户端代码都不关闭套接字,都交由退出进程的时候由系统关闭,不知道这种风格好不好。由于学习。。。写的是ANSI C程序,用gcc编译-_-!
unp.h是《Unix Network Programming》源代码中的公用头文件,makefile可能也得注意一下,为了图省事,我用了其源代码中的Make.defines,因为这样比自己写简单多了:),makefile就不贴了,没有什么学习意义。
运行效果如下:
客户端运行:
./TestSelectCli 127.0.0.1 1000
Conncet OK
127.0.0.1:16777343 Echo 1.
laptop:~/unpv1/unpv13e/MyTest$ ./TestSelectCli 127.0.0.1 1001
Conncet OK
127.0.0.1:16777343 Echo 2.
laptop:~/unpv1/unpv13e/MyTest$ ./TestSelectCli 192.168.0.138 1000
Conncet OK
192.168.0.138:2315299008 Echo 1.
laptop:~/unpv1/unpv13e/MyTest$ ./TestSelectCli 192.168.0.138 1001
Conncet OK
192.168.0.138:2315299008 Echo 2.
服务器端输出:
2315299008 Echo 1.
16777343 Echo 1.
16777343 Echo 2.
2315299008 Echo 1.
2315299008 Echo 2.
服务器端源代码:
1 #include"unp.h"
2
3
4 voidstr_echo1(intconnfd);
5 voidstr_echo2(intconnfd);
6
7 intmain(intargc, char**argv)
8 {
9 structsockaddr_in cliaddr;
10 pid_t childpid;
11
12 /*Bind 1000 port to listen socket 1 */
13 intlistenfd1 = Socket(AF_INET, SOCK_STREAM, 0);
14
15 structsockaddr_in servaddr;
16 bzero(&servaddr, sizeof(servaddr));
17 servaddr.sin_family = AF_INET;
18 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
19 servaddr.sin_port = htons(1000);
20
21 Bind(listenfd1, (SA *)&servaddr, sizeof(servaddr));
22
23 Listen(listenfd1, LISTENQ);
24
25 /*Bind 1001 port to listen socket 2*/
26 intlistenfd2 = Socket(AF_INET, SOCK_STREAM, 0);
27
28 structsockaddr_in servaddr2;
29 bzero(&servaddr2, sizeof(servaddr2));
30 servaddr2.sin_family = AF_INET;
31 servaddr2.sin_addr.s_addr = htonl(INADDR_ANY);
32 servaddr2.sin_port = htons(1001);
33
34 Bind(listenfd2, (SA *)&servaddr2, sizeof(servaddr2));
35
36 Listen(listenfd2, LISTENQ);
37
38 /*Initialize fd_set struct */
39 intmaxfdp1 = max(listenfd1, listenfd2) + 1;
40 fd_set rset;
41 FD_ZERO(&rset);
42
43 /*Select from this two listen socket */
44 for( ; ; )
45 {
46 FD_SET(listenfd1, &rset);
47 FD_SET(listenfd2, &rset);
48
49 intnready = -1;
50 if( (nready = select(maxfdp1, &rset, NULL, NULL, NULL)) < 0)
51 {
52 if(EINTR== errno)
53 {
54 continue;
55 }
56 else
57 {
58 err_sys("Select error.");
59 }
60 }
61
62 /*some one listening socket is readable.*/
63 if(FD_ISSET(listenfd1, &rset))
64 {
65 socklen_t len = sizeof(cliaddr);
66 intconnfd = Accept(listenfd1, (SA *)&cliaddr, &len);
67
68 if( 0== (childpid = Fork()) )
69 {
70 /*child process */
71 Close(listenfd1);
72
73 str_echo1(connfd);
74 exit(0);
75 }
76
77 /*parent process*/
78 Close(connfd);
79
80 }
81
82
83 if(FD_ISSET(listenfd2, &rset))
84 {
85 socklen_t len = sizeof(cliaddr);
86 intconnfd = Accept(listenfd2, (SA *)&cliaddr, &len);
87
88 if( 0== (childpid = Fork()) )
89 {
90 /*child process */
91 Close(listenfd2);
92
93 str_echo2(connfd);
94 exit(0);
95 }
96
97 /*parent process*/
98 Close(connfd);
99
100 }
101
102 }
103
104 exit(0);
105 }
106
107 voidstr_echo1(intconnfd)
108 {
109 structsockaddr_in clientAddr;
110 socklen_t len = sizeof(clientAddr);
111
112 if(getpeername(connfd, (SA*) &clientAddr, &len) < 0)
113 {
114 return;
115 }
116
117 charlcBuffer[MAXLINE] = {0};
118 sprintf(lcBuffer, "%uEcho 1.", clientAddr.sin_addr.s_addr);
119
120 printf("%s/n", lcBuffer);
121
122 Write(connfd, lcBuffer, MAXLINE);
123 }
124
125
126 voidstr_echo2(intconnfd)
127 {
128 structsockaddr_in clientAddr;
129 socklen_t len = sizeof(clientAddr);
130
131 if(getpeername(connfd, (SA*) &clientAddr, &len) < 0)
132 {
133 return;
134 }
135
136
137 charlcBuffer[MAXLINE] = {0};
138 sprintf(lcBuffer, "%uEcho 2.", clientAddr.sin_addr.s_addr);
139
140 printf("%s/n", lcBuffer);
141
142 Write(connfd, lcBuffer, MAXLINE);
143 }
144
145
客户端源代码:
1 #include"unp.h"
2
3 intmain(intargc, char**argv)
4 {
5 intsockfd, n;
6 char recvline[MAXLINE + 1];
7 structsockaddr_in servaddr;
8
9 if(argc != 3)
10 err_quit("usage: a.out <IPaddress> <IPPort>");
11
12 intport = atoi(argv[2]);
13
14 if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
15 err_sys("socket error");
16
17 bzero(&servaddr, sizeof(servaddr));
18 servaddr.sin_family = AF_INET;
19 servaddr.sin_port = htons(port);
20 if(inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)
21 err_quit("inet_pton error for %s", argv[1]);
22
23 if(connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0)
24 err_sys("connect error");
25
26 printf("Conncet OK/n");
27
28 while( (n = read(sockfd, recvline, MAXLINE)) > 0) {
29 recvline[n] = 0;/*null terminate */
30
31 /*change number string to number and to ip string */
32 structin_addr svraddr;
33 svraddr.s_addr = strtoul(recvline, NULL, 10);
34 char*pszsvraddr = inet_ntoa(svraddr);
35
36 printf("%s:%s/n", pszsvraddr, recvline);
37 }
38 if(n < 0)
39 err_sys("read error");
40
41 exit(0);
42 }
write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie
分享到:
相关推荐
在这个场景中,`select`模型是一种常用的I/O多路复用技术,它允许程序同时监听多个网络连接,提高服务器的并发处理能力。`select`模型在服务端和客户端的实现中都扮演着重要角色。以下是对`select`模型代码实现的...
TCP 一对多通信的程序(MFC 对话框程序),就是服务器端利用Select模型技术, 能同时接收多个客户端的消息, 其次, 服务器端还能将消息群发给所有已连接的客户端, 实现的基本思路 是使用Select模型的套接字集合...
`select`函数的使用可以避免程序陷入繁忙等待,提高系统资源利用率,实现一个服务器与多个客户端的高效通信。 `select`函数的基本语法如下: ```c int select(int nfds, fd_set *readfds, fd_set *writefds, fd_...
在VS2010环境下,开发者可以利用Winsock库和Select模型实现高效的网络通信。通过阅读和学习提供的`SocketSelect2010`源码,你可以深入了解这一机制,并将其应用到实际项目中,提高程序的并发处理能力。
本文将深入探讨在`socket`编程中的一种多路复用技术——`select`模型,以及如何利用它来构建一个简单的网络聊天室,类似于QQ群组。 `socket`是操作系统提供的一种接口,用于在网络上的进程间进行通信。它支持TCP...
在IT行业中,网络通信是计算机系统之间交换信息的关键部分,特别是在分布式系统和互联网环境中。...通过阅读和理解`selServer.cpp`和`client.cpp`的代码,可以深入学习select模型在实际应用中的工作原理和实现细节。
TCP 一对多通信的程序(MFC 对话框程序),就是服务器端利用Select模型技术, 能同时接收多个客户端的消息, 其次, 服务器端还能将消息群发给所有已连接的客户端, 实现的基本思路 是使用Select模型的套接字集合...
"Select模型搭建200服务器"的主题聚焦于如何利用线程池技术和Select模型来设计一个能够处理万人级并发访问的服务器。这个话题涉及到的核心知识点包括线程池、I/O多路复用(Select模型)以及数据同步策略。 首先,...
本篇文章将深入探讨使用C++实现的基于`select`模型的异步SOCKET通信,特别关注如何构建一个简单的聊天室服务端和客户端。 首先,`select`模型是网络编程中处理多路复用I/O(Multiplexing I/O)的一种方式,允许程序...
本DEMO着重探讨服务端的设计,特别是利用select和event_select模型来实现高并发的网络通信。 TCP/IP协议栈是互联网的核心,它由四层结构组成:应用层、传输层、网络层和数据链路层。在C/S模型中,应用层通常采用...
在IT行业中,"select模型服务器"是指一种基于C++编程语言实现的服务器架构,它利用了操作系统提供的`select`函数来处理并发连接。`select`是多路复用I/O模型的一种,允许程序同时监控多个文件描述符(通常是套接字)...
在深入探讨socket编程时,select模型是一种常用的I/O多路复用技术,它允许程序监视多个文件描述符以查看它们是否处于可读、可写或异常状态。...掌握select模型对于进行高性能网络编程和服务器端软件开发是非常重要的。
本文将深入探讨这个模型,并结合提供的文件"tClient"和"tServer",来阐述如何在C/S(客户端/服务器)模型中实现基于TCP/IP通信的select模型。 首先,select模型的核心在于其函数`select()`,该函数允许程序在一个或...
本文将深入探讨基于"select模型"的Socket服务器,它是一个能够处理多客户端连接请求的关键技术。 首先,让我们理解什么是Socket。Socket是网络编程中的一个接口,它允许两个程序通过网络进行通信。在操作系统层面,...
在这个“select模型简单示例”中,我们将深入探讨`select`函数的工作原理,以及如何在一个简单的多线程环境中应用它。 首先,`select`函数的核心在于其能够等待一组文件描述符中的任意一个变为可读、可写或出现错误...
在本文中,我们将深入探讨如何使用SELECT模型来实现一个并发的TCP服务器,特别是在Ubuntu Linux系统环境下。该服务器能够同时处理多个客户端的连接请求,确保服务的高效和稳定。 首先,我们要明确SELECT函数在并发...
Select模型特别适用于需要监听多个套接字的应用场景,例如服务器程序需要同时处理来自多个客户端的请求。在这种情况下,使用Select模型可以显著提高程序的并发处理能力。 ### `select()`函数详解 #### 函数原型 `...
- **简单多连接服务器**:对于需要同时处理多个客户端连接的简单服务器,`select`模型是一个不错的选择,特别是当连接数量不是特别大的时候。 - **资源有限的环境**:在资源有限的嵌入式系统中,`select`由于其轻量...
WIN32平台下一个 select 模型(服务器端)的简单聊天代码
Select模型是一种常用的I/O多路复用技术,在网络编程中被广泛应用于监听多个套接字的状态变化。该模型允许一个进程同时监控多个文件描述符(例如:套接字),并且可以在任一文件描述符准备好进行读写操作时得到通知...