-
Notifications
You must be signed in to change notification settings - Fork 0
/
c++实战——多人会话聊天室2.html
209 lines (197 loc) · 15.1 KB
/
c++实战——多人会话聊天室2.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="author" content="littlewhite" />
<meta name="copyright" content="littlewhite" />
<meta property="og:type" content="article" />
<meta name="twitter:card" content="summary">
<meta name="keywords" content="c++, Language, " />
<meta property="og:title" content="c++实战——多人会话聊天室2 "/>
<meta property="og:url" content="https://chukeer.github.io/c++实战——多人会话聊天室2.html" />
<meta property="og:description" content="前面已经讲过一次多人会话聊天室的实现C++实战——多人会话聊天室(一),只不过上一篇是用最简单的方式,服务端每接收一个连接就起一个线程,而且是阻塞模式的,也就是说服务端每次调用accept函数时会一直等待有客户端连接上才会返回。今天介绍一种基于epoll模型的非阻塞方式的实现。 === 阻塞与非阻塞¶ 顾名思义,阻塞就是当你调用一个函数后它会一直等在那里,知道某个信号叫醒它,最典型的例子就是read之类的函数,当你调用时它会等待标准输入,直到你在屏幕上输完敲下回车,它才会继续执行。Linux默认IO都是阻塞模型的 非阻塞就是当你调用函数之后它会立马返回,同样还是拿read举例,它不会阻塞在屏幕上等待你输入,而是立马返回,如果返回错误,那就代表没有数据可读。下面的例子可以大致说明一下差别 #include <unistd.h> #include <stdio.h> #include <fcntl.h> #include <stdlib.h> int main(int argc, char *argv[]) { int res; res = fcntl(0, F_GETFL ..." />
<meta property="og:site_name" content="楚客" />
<meta property="og:article:author" content="littlewhite" />
<meta property="og:article:published_time" content="2014-05-19T00:00:00+08:00" />
<meta property="" content="2014-05-19T00:00:00+08:00" />
<meta name="twitter:title" content="c++实战——多人会话聊天室2 ">
<meta name="twitter:description" content="前面已经讲过一次多人会话聊天室的实现C++实战——多人会话聊天室(一),只不过上一篇是用最简单的方式,服务端每接收一个连接就起一个线程,而且是阻塞模式的,也就是说服务端每次调用accept函数时会一直等待有客户端连接上才会返回。今天介绍一种基于epoll模型的非阻塞方式的实现。 === 阻塞与非阻塞¶ 顾名思义,阻塞就是当你调用一个函数后它会一直等在那里,知道某个信号叫醒它,最典型的例子就是read之类的函数,当你调用时它会等待标准输入,直到你在屏幕上输完敲下回车,它才会继续执行。Linux默认IO都是阻塞模型的 非阻塞就是当你调用函数之后它会立马返回,同样还是拿read举例,它不会阻塞在屏幕上等待你输入,而是立马返回,如果返回错误,那就代表没有数据可读。下面的例子可以大致说明一下差别 #include <unistd.h> #include <stdio.h> #include <fcntl.h> #include <stdlib.h> int main(int argc, char *argv[]) { int res; res = fcntl(0, F_GETFL ...">
<title>c++实战——多人会话聊天室2 · 楚客
</title>
<!--
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet">
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.1/css/font-awesome.css" rel="stylesheet">
--!>
<link href="https://chukeer.github.io/theme/css/bootstrap-combined.min.css" rel="stylesheet">
<link href="https://chukeer.github.io/theme/css/font-awesome.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="https://chukeer.github.io/theme/css/pygments.css" media="screen">
<link rel="stylesheet" type="text/css" href="https://chukeer.github.io/theme/tipuesearch/tipuesearch.css" media="screen">
<link rel="stylesheet" type="text/css" href="https://chukeer.github.io/theme/css/elegant.css" media="screen">
<link rel="stylesheet" type="text/css" href="https://chukeer.github.io/theme/css/custom.css" media="screen">
</head>
<body>
<div id="content-sans-footer">
<div class="navbar navbar-static-top">
<div class="navbar-inner">
<div class="container-fluid">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<a class="brand" href="https://chukeer.github.io/"><span class=site-name>楚客</span></a>
<div class="nav-collapse collapse">
<ul class="nav pull-right top-menu">
<li ><a href="https://chukeer.github.io">Home</a></li>
<li ><a href="https://chukeer.github.io/categories.html">Categories</a></li>
<li ><a href="https://chukeer.github.io/tags.html">Tags</a></li>
<li ><a href="https://chukeer.github.io/archives.html">Archives</a></li>
<li><form class="navbar-search" action="https://chukeer.github.io/search.html" onsubmit="return validateForm(this.elements['q'].value);"> <input type="text" class="search-query" placeholder="Search" name="q" id="tipue_search_input"></form></li>
</ul>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row-fluid">
<div class="span1"></div>
<div class="span10">
<article>
<div class="row-fluid">
<header class="page-header span10 offset2">
<h1><a href="https://chukeer.github.io/c++实战——多人会话聊天室2.html"> c++实战——多人会话聊天室2 </a></h1>
</header>
</div>
<div class="row-fluid">
<div class="span2 table-of-content">
<nav>
<h4>Contents</h4>
<div class="toc">
<ul>
<li><a href="#_1">阻塞与非阻塞</a></li>
</ul>
</div>
</nav>
</div>
<div class="span8 article-content">
<p>前面已经讲过一次多人会话聊天室的实现<a href="http://littlewhite.us/archives/109">C++实战——多人会话聊天室(一)</a>,只不过上一篇是用最简单的方式,服务端每接收一个连接就起一个线程,而且是阻塞模式的,也就是说服务端每次调用accept函数时会一直等待有客户端连接上才会返回。今天介绍一种基于epoll模型的非阻塞方式的实现。</p>
<p>===</p>
<h4 id="_1">阻塞与非阻塞<a class="headerlink" href="#_1" title="Permanent link">¶</a></h4>
<p>顾名思义,阻塞就是当你调用一个函数后它会一直等在那里,知道某个信号叫醒它,最典型的例子就是read之类的函数,当你调用时它会等待标准输入,直到你在屏幕上输完敲下回车,它才会继续执行。Linux默认IO都是阻塞模型的<br/>
非阻塞就是当你调用函数之后它会立马返回,同样还是拿read举例,它不会阻塞在屏幕上等待你输入,而是立马返回,如果返回错误,那就代表没有数据可读。下面的例子可以大致说明一下差别</p>
<div class="highlight"><pre><span></span><span class="cp">#include</span> <span class="cpf"><unistd.h></span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf"><stdio.h></span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf"><fcntl.h></span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf"><stdlib.h></span><span class="cp"></span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span>
<span class="p">{</span>
<span class="kt">int</span> <span class="n">res</span><span class="p">;</span>
<span class="n">res</span> <span class="o">=</span> <span class="n">fcntl</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">F_GETFL</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">==</span> <span class="n">res</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">perror</span><span class="p">(</span><span class="s">"fcntl error!"</span><span class="p">);</span>
<span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
<span class="cp">#ifdef NONBLOCK</span>
<span class="n">res</span> <span class="o">|=</span> <span class="n">O_NONBLOCK</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">fcntl</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">F_SETFL</span><span class="p">,</span> <span class="n">res</span><span class="p">)</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">perror</span><span class="p">(</span><span class="s">"error"</span><span class="p">);</span>
<span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
<span class="cp">#endif</span>
<span class="kt">char</span> <span class="n">buf</span><span class="p">[</span><span class="mi">100</span><span class="p">];</span>
<span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">n</span> <span class="o">=</span> <span class="n">read</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">buf</span><span class="p">,</span> <span class="mi">100</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">==</span> <span class="n">n</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">perror</span><span class="p">(</span><span class="s">"read error"</span><span class="p">);</span>
<span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">else</span>
<span class="p">{</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"read %d characters</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">n</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>代码的意思很好理解,我们从标准输入读取数据,并打印出读取了多少字节,但是我们做了个测试,当定义了宏NONBLOCK后,我们会将标准输入句柄改变成非阻塞的,宏可以通过编译时的-D参数指定,我们分别按如下指令编译,假设文件名为test.cpp</p>
<div class="highlight"><pre><span></span>g++ test.cpp -o test_block
g++ test.cpp -D NONBLOCK -o test_nonblock
</pre></div>
<p>然后我们运行./test_block,程序会阻塞在屏幕上等待输入,输入hello world并回车,程序运行结束<br/>
但是当我们运行./test_nonblock时,程序报错<em>read error: Resource temporarily unavailable</em>,这是因为此时的标准输入是非阻塞模式,当调用read后它会立马返回,而此时并没有数据可读取,就会返回错误,但是我们按如下方式就可运行成功</p>
<div class="highlight"><pre><span></span>echo "hello world" | ./test_nonblock
</pre></div>
<p>因为在read调用之前,管道里已经有了数据,所以它会去读取管道里的数据而不会出错。</p>
<p>to be continued...</p>
<hr/>
<aside>
<nav>
<ul class="articles-timeline">
<li class="previous-article">« <a href="https://chukeer.github.io/vpn简介以及国内外分流设置.html" title="Previous: vpn简介以及国内外分流设置">vpn简介以及国内外分流设置</a></li>
<li class="next-article"><a href="https://chukeer.github.io/glog安装及使用.html" title="Next: glog安装及使用">glog安装及使用</a> »</li>
</ul>
</nav>
</aside>
</div>
<section>
<div class="span2" style="float:right;font-size:0.9em;">
<table class="table">
<!-- <time pubdate="pubdate" datetime="2014-05-19T00:00:00+08:00"> 5 19, 2014</time> -->
<tr>
<td>Published</td>
<td><time pubdate="pubdate" datetime="2014-05-19T00:00:00+08:00">2014- 5-19</time></td>
</tr>
<tr>
<td>Category</td>
<td><a class="category-link" href="https://chukeer.github.io/categories.html#language-ref">Language</a></td>
</tr>
<tr>
<td>Tags</td>
<td>
<ul class="list-of-tags tags-in-article">
<li><a href="https://chukeer.github.io/tags.html#c-ref">c++
<span>15</span>
</a></li>
</ul>
</td>
</tr>
</table>
</div>
</section>
</div>
</article>
</div>
<div class="span1"></div>
</div>
</div>
<div id="push"></div>
</div>
<footer>
<div id="footer">
<ul class="footer-content">
<li class="elegant-power">Powered by <a href="http://getpelican.com/" title="Pelican Home Page">Pelican</a>. Theme: <a href="http://oncrashreboot.com/pelican-elegant" title="Theme Elegant Home Page">Elegant</a> by <a href="http://oncrashreboot.com" title="Talha Mansoor Home Page">Talha Mansoor</a></li>
</ul>
</div>
</footer> <!--
<script src="http://code.jquery.com/jquery.min.js"></script>
<script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>
-->
<script src="https://chukeer.github.io/theme/js/jquery.min.js"></script>
<script src="https://chukeer.github.io/theme/js/bootstrap.min.js"></script>
<script>
function validateForm(query)
{
return (query.length > 0);
}
</script>
<script>
$("div.article-content table").addClass("table table-hover");
</script>
</body>
<!-- Theme: Elegant built for Pelican
License : http://oncrashreboot.com/pelican-elegant -->
</html>