Tinychatserver:一个简易的命令行群聊程序

这是学习网络编程后写的一个练手的小程序,可以帮助复习socket,I/O复用,非阻塞I/O等知识点。

通过回顾写的过程中遇到的问题的形式记录程序的关键点,最后给出完整程序代码。

0. 功能

编写一个简易群聊程序,程序具备的基本功能:

服务器:支持多个客户端连接,并将每个客户端发过来的消息发给所有其他的客户端

客户端:能够连接服务器,并向服务器发送消息,同时接收服务器发过来的任何消息

1. Server I/O模型

采用事件驱动(I/O复用)+ 非阻塞I/O的模型,即Reactor模式。I/O复用采用linux下的epoll机制。

相关API介绍见最后,先梳理几个写程序的时候想到的问题。

1.1  I/O复用为什么搭配非阻塞I/O?(select/epoll返回可读后还用非阻塞是不是没有意义?)

select/epoll返回了可读,并不一定代表能读,在返回可读到调用read函数之间,是有时间间隙的。内核可能把数据丢失,也可能存在比如多个线程监听该socket,

数据被别人读走的情况。所以这里使用非阻塞I/O是有意义的。

1.2 epoll的条件触发LT(水平触发)和边缘触发ET区别,如何正确地处理ET模式下的读操作?

简单讲,以读取数据操作举例。条件触发,只要输入缓冲中还有数据,就会以事件方式再次注册;

而边缘触发中仅在输入缓冲收到数据时注册一次该事件(你没读完也epoll_wait也不再返回了)。

所以如果使用边缘触发发生输入相关事件,需要读取输入缓冲中的全部数据。方法是一直读,直到 #include <iostream> #include <list> #include <sys/types.h> #include <sys/socket.h> #include <netinet/ #include <arpa/inet.h> #include <sys/epoll.h> #include <fcntl.h> #include <errno.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include < list< fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, )| ev.data.fd = ev.events = ev.events = EPOLLIN | epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, & printf( printf( ) clients_list.remove(clientfd); printf( ) { send(clientfd, CAUTION, strlen(CAUTION), list< ) < ) { perror( #include serverAddr.sin_family = serverAddr.sin_port = serverAddr.sin_addr.s_addr = perror( printf( perror( exit(- perror( exit(- printf( perror( exit(- printf( addfd(epfd, listener, perror( printf( ; i < epoll_events_count; ++ socklen_t client_addrLength = printf( addfd(epfd, clientfd, printf( printf( printf( perror( exit(- printf( ) { perror( close(listener); close(epfd); }

  
 #include  
                   serverAddr.sin_family =     serverAddr.sin_port =     serverAddr.sin_addr.s_addr = 
               ) { perror(     
                   perror(         exit(-                                 buf[str_len] =      printf(         
       pid_t pid =                                           
       
                      memset(buf, ,                                          buf[str_len] =          printf(   
                      memset(buf, ,                             }
更多相关文章
  • NodeJS用递归实现异步操作的链式调用,完成一个简易的命令行输入输出REPL交互接口
    REPL —— Read-Eval-Print-Loop. 00.一门好的编程语言的必要条件 REPL并不是什么高大上的东西,简单的说就是一个从命令行程序,读取终端输入,处理,打印结果,如此循环.这是一门比较全面的编程语言的基础. 刚开始接触NodeJS,以为就是一个服务端Js,但学习了一段时间之后 ...
  • 参考自:http://blog.csdn.net/xxyyww/article/details/5784803 前言: 在命令行运行JAVA的时候,要做的事情就不是点一下鼠标就可以了.如果再用到第三方JAR包,命令就更长了.一个比较好的方法就是使用ant,不过我发现一个问题,在命令行中使用ant的时 ...
  • 如何在Linux命令行中下载GOG游戏
    如果你是一个游戏玩家同时也是一个Linux用户,你可能很高兴在GOG在几个月前宣布它会在你最喜欢的操作系统上推出游戏.如果你之前从来没有听说过GOG,我鼓励你看看他们的产品目录中的“很棒的老游戏”,价格合理,无DRM限制,而且充满了很棒的东西.虽然Windows上的GOG客户端已经存在了很长的时间, ...
  • Linux系统入门学习:如何在命令行下压缩JPEG图像
    问题: 我有许多数码照相机拍出来的照片.我想在上传到Dropbox之前,优化和压缩下JPEG图片.有没有什么简单的方法压缩JPEG图片并不损耗他们的质量?如今拍照设备(如智能手机.数码相机)拍出来的图片分辨率越来越大.甚至3630万像素的Nikon D800已经冲入市场,并且这个趋势根本停不下来.如 ...
  • 使用 Apache Commons CLI 开发命令行工具示例
    目录概念说明Apache Commons CLI 简介CLI 定义阶段CLI 解析阶段CLI 询问阶段代码示例 概念说明 Apache Commons CLI 简介Apache Commons CLI 是 Apache 下面的一个解析命令行输入的工具包,该工具包还提供了自动生成输出帮助文档的功能.  ...
  • rtorrent强大的命令行BT客户端
    如果你不使用torrent命令行客户端是担心它太复杂,那么,请重新考虑下.我相信一旦使用过了基于命令行的BT客户端,你就会离不开它:你可以非常轻松地在你的终端窗口启动和监控进度.在这篇文章中,我们将会介绍一个强大的命令行BT客户端 - rtorrent .NOTE - 文中展示的所有示例和指令都已经 ...
  • JasperStarter 1.1.0 发布,JasperReports 命令行启动器
    JasperStarter 是一个 JasperReports 的命令行启动器.JasperStarter 1.1.0 支持报表参数的提示.JasperStarter 的下载地址:
  • JasperStarter 1.4.0,JasperReports命令行启动器
    JasperStarter 1.4.0 发布了,该版本升级 JasperReports 库到 5.1.2 版本.JasperStarter 是一个 JasperReports 的命令行启动器.JasperStarter 的下载地址:
  • JasperStarter 1.3.0,JasperReports命令行启动器
    JasperStarter 1.3.0 更新 JasperReports 库到 5.1.0 版本.JasperStarter 是一个 JasperReports 的命令行启动器.JasperStarter 的下载地址:
一周排行