上一小节我们讲了使用select来避免使用多进程的资源浪费问题。上次只是实现了从多个客户端发送数据给服务器端,接下来就要实现从服务器端发送数据给各个客户端。

  使用select多路转换处理聊天程序2

  client.c 使用上一节用的那个,在那个基础上修改下面几句

     //send-recv 一些返回指没有判断,具体可以看server.c
if((pid=fork())<)
{
perror("fork error\n");
}
else if(pid==)/*child*/
{
while()
{
fgets(sendBuf,MAX_BUF,stdin);
if(send(sockfd,sendBuf,strlen(sendBuf),)==-)
{
perror("fail to receive datas.");
}
memset(sendBuf,,sizeof(sendBuf));
}
}
else
{
while()
{
if((recvSize=recv(sockfd,recvBuf,MAX_BUF,)==-))
{
printf("Server maybe shutdown!");
break;
}
printf("Server:%s\n",recvBuf);
memset(recvBuf,,sizeof(recvBuf));
}
kill(pid,SIGKILL);
} close(sockfd); return ;
}

  server.c 我们在上一小节的基础上加上一个处理服务器stdin读取数据,然后遍历所有fd_A里面还连接着的客户端,然后一个一个的发送数据。

     while()
{
FD_ZERO(&servfd);//清空所有server的fd
FD_ZERO(&recvfd);//清空所有client的fd
FD_SET(sockfd,&servfd);
//timeout.tv_sec=30;//可以减少判断的次数
switch(select(max_servfd+,&servfd,NULL,NULL,&timeout))
{
          ...
}
//FD_COPY(recvfd,servfd);
for(i=;i<MAX_CON_NO;i++)//最大队列进行判断,优化的话,可以使用链表
{
if(fd_A[i]!=)
{
FD_SET(fd_A[i],&recvfd);
}
} switch(select(max_recvfd+,&recvfd,NULL,NULL,&timeout))
{
          ... } /*用于检测stdin是否有数据*/
FD_ZERO(&servfd);
FD_SET(STDIN_FILENO,&servfd); switch(select(STDIN_FILENO+,&servfd,NULL,NULL,&timeout))
{
case -:
break;
case :
break;
default:
/*send datas to client*/
if(FD_ISSET(STDIN_FILENO,&servfd))
{
fgets(sendBuf,MAX_DATA_SIZE,stdin);
for(i=;i<MAX_CON_NO;i++)
{
if(fd_A[i]!=)
{
printf("数据发往%d,",fd_A[i]);
if((sendSize=send(fd_A[i],sendBuf,strlen(sendBuf),))!=strlen(sendBuf))
{
perror("fail");
exit();
}
else
{
printf("Success\n");
}
}
}
memset(sendBuf,,MAX_DATA_SIZE);
fflush(stdin);
}
break;
}
}
return ;
}

  废话不多说,直接上运行时的截图

  程序运行的顺序是,运行server,然后运行client1,server发送data1,client2连接server,server发送data2,client3连接server,server发送data3,此时client1退出连接,server获取fd 4 close,发送data4的时候没有发送给fd4。然后client4连接上去。分配为fd7。(虽然fd4已经关闭了,按说可以给client4分配fd4,不过太麻烦我这里就没有实现。)

  实现聊天室功能

  接下来就是实现聊天室功能。上面server.c中有三个select,第一个是处理随时可能来的客户端连接,第二个select是处理随时可能从客户器端来的数据,第三个select是处理随时可能从控制台输入数据,并send到各个客户端。要实现聊天室功能,就对第二个和第三个select进行合并。具体不多说,直接上代码

  client.c 基本不变

  server.c

 #include <stdio.h>
   ...
int main(int argc,char *argv[])
{
    ...
while()
{
FD_ZERO(&servfd);//清空所有server的fd
FD_ZERO(&recvfd);//清空所有client的fd
FD_SET(sockfd,&servfd);
//timeout.tv_sec=30;//可以减少判断的次数
switch(select(max_servfd+,&servfd,NULL,NULL,&timeout))
{
...
}
       ...
switch(select(max_recvfd+,&recvfd,NULL,NULL,&timeout))
{
case -:
//select error
break;
case :
//timeout
break;
default:
for(i=;i<conn_amount;i++)
{
if(FD_ISSET(fd_A[i],&recvfd))
{
/*receive datas from client*/
if((recvSize=recv(fd_A[i],recvBuf,MAX_DATA_SIZE,))==- || recvSize==)
{
//perror("fail to receive datas");
//表示该client是关闭的
printf("fd %d close\n",fd_A[i]);
FD_CLR(fd_A[i],&recvfd);
fd_A[i]=;
}
else//客户端发送数据过来,然后这里进行转发
{
/*send datas to client*/
for(j=;j<MAX_CON_NO;j++)
{
if(fd_A[j]!=&&i!=j)
{
printf("数据发往%d,",fd_A[j]);
if((sendSize=send(fd_A[j],recvBuf,strlen(recvBuf),))!=strlen(recvBuf))
{
perror("fail");
exit();
}
else
{
printf("Success\n");
}
}
}
//可以判断recvBuf是否为bye来判断是否可以close
memset(recvBuf,,MAX_DATA_SIZE);
}
}
}
break;
}
}
return ;
}

  直接上运行时图片

  各个程序运行的循序是先运行server,然后运行client1,client2,然后cli1发送数据data1,此时cli2接收到server发来的转发数据,然后... ...

  好了,到现在为止已经完成了聊天室功能了,还可以随时进入随时出来。好像还不错的样子。下一节就介绍引入用户名登陆的字符界面(由于我不会图形化界面,所以就不花时间去学那个了,至于字符界面下有个curses.h据说可以弄得很好看,我这里就不弄了。有兴趣的可以去弄一下),还有一些人性化的中文提示,然后整理一下代码。由于基本没有什么技术含量,所以如果到时候篇幅不够就再加个数据库设计,考虑使用数据库来保存用户(为了方便就使用mysql吧)。

  小小剧透一下,如果接下来有时间将会实现以下功能 用户功能,指令功能,私聊功能,vip功能,文件发送功能,多服务器问题

  本文地址: http://www.cnblogs.com/wunaozai/p/3871563.html

Socket网络编程--聊天程序(5)的更多相关文章

  1. Socket网络编程--聊天程序(9)

    这一节应该是聊天程序的最后一节了,现在回顾我们的聊天程序,看起来还有很多功能没有实现,但是不管怎么说,都还是不错的.这一节我们将讲多服务器问题(高大上的说法就是负载问题了.)至于聊天程序的文件发送(也 ...

  2. Socket网络编程--聊天程序(1)

    很早的一段时间,看了APUE和UNPv1了解了网络编程,但是但是只是看而已,没有具体的实践,趁现在没有什么事做,就来实践了解一下网络编程.写博客保存下来,方便以后用到的时候可以查到. 此次的聊天程序是 ...

  3. Socket网络编程--聊天程序(8)

    上一节已经完成了对用户的身份验证了,既然有了验证,那么接下来就能对不同的客户端进行区分了,所以这一节讲实现私聊功能.就是通过服务器对客户端的数据进行转发到特定的用户上, 实现私聊功能的聊天程序 实现的 ...

  4. Socket网络编程--聊天程序(6)

    这一小节将增加一个用户的结构体,用于保存用户的用户名和密码,然后发给服务器,然后在服务器进行判断验证.这里就有一个问题,以前讲的就是发送字符串是使用char类型进行传输,然后在服务器进行用同样是字符串 ...

  5. Socket网络编程--聊天程序(7)

    接上一小节,本来是计划这一节用来讲数据库的增删改查,但是在实现的过程中,出现了一点小问题,也不是技术的问题,就是在字符界面上比较不好操作.比如要注册一个帐号,就需要弄个字符界面提示,然后输入数字表示选 ...

  6. Socket网络编程--聊天程序(3)

    上一小节,已经讲到可以每个人多说话,而且还没有限制,简单的来说,我们已经完成了聊天的功能了,那么接下来我们要实现什么功能呢?一个聊天程序至少应该支持一对多的通讯吧,接下来就实现多个客户端往服务器发送数 ...

  7. Socket网络编程--聊天程序(4)

    上一小节讲到可以实现多客户端与服务器进行通讯,对于每一个客户端的连接请求,服务器都要分配一个进程进行处理.对于多用户连接时,服务器会受不了的,而且还很消耗资源.据说有个select函数可以用,好像还很 ...

  8. Socket网络编程--聊天程序(2)

    上一节简单如何通过Socket创建一个连接,然后进行通信.只是每个人只能说一句话.而且还是必须说完才会接收到信息,总之是很不方便的事情.所以这一小节我们将对上一次的程序进行修改,修改成每个人可以多说话 ...

  9. Socket网络编程--小小网盘程序(5)

    各位好呀!这一小节应该就是这个小小网盘程序的最后一小节了,这一节将实现最后的三个功能,即列出用户在服务器中的文件列表,还有删除用户在服务器中的文件,最后的可以共享文件给好友. 列出用户在服务器中的文件 ...

随机推荐

  1. 《Gradle权威指南》--Android Gradle高级自定义

    No1: 指定共享库 <uses-library android:name="com.google.android.maps" android:required=" ...

  2. hdu 2126 Buy the souvenirs 【输出方案数】【01背包】(经典)

    题目链接:https://vjudge.net/contest/103424#problem/K 转载于:https://blog.csdn.net/acm_davidcn/article/detai ...

  3. poj2230 Watchcow【欧拉回路】【输出路径】(遍历所有边的两个方向)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4392 题目大意: 一个图,要将每条边恰好遍历两遍,而且要以不同的方向,还要回到原点. dfs解法    ...

  4. P3719 [AHOI2017初中组]rexp

    P3719 [AHOI2017初中组]rexp一开始想的是类似计算式子的值的东西,用栈.然后发现处理最大值很麻烦,因为处理的很像子过程,所以考虑递归来做.碰到'('就递归一次,碰到'|'就取最大值再递 ...

  5. 前端解读面向切面编程(AOP)

    前言 面向对象(OOP)作为经典的设计范式,对于我们来说可谓无人不知,还记得我们入行起始时那句经典的总结吗-万事万物皆对象. 是的,基于OOP思想封装.继承.多态的特点,我们会自然而然的遵循模块化.组 ...

  6. LoRaWAN 1.1 网络协议规范 - 2 LoRaWAN选项介绍

    LoRaWAN 1.1 网络协议规范 LoRaWAN 1.1 版本封稿很久了也没有完整啃过一遍,最近边啃边翻译,趁着这个机会把它码下来. 如果觉得哪里有问题,欢迎留言斧正. 翻译不易,转载请申明出处和 ...

  7. SQL RAISERROR 用法

    ) ), YOUR UNIQUEIDENTIFIER KEY) ,, @raiseErrorCode) RAISERROR ( N'This is message %s %d.', -- Messag ...

  8. BZOJ.3575.[HNOI2014]道路堵塞(最短路 动态SPFA)

    题目链接 \(Description\) 给你一张有向图及一条\(1\)到\(n\)的最短路.对这条最短路上的每条边,求删掉这条边后\(1\)到\(n\)的最短路是多少. \(Solution\) 枚 ...

  9. bootstrap中的对话框-dialog

    <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <meta name= ...

  10. log4j.properties_配置

    参考:http://blog.csdn.net/qq_30175203/article/details/52084127 参考:http://zengxiantao.iteye.com/blog/18 ...