/*server*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <stdlib.h>
#include "common.h"
#include <iostream>
void process_cli(Client *client, char* recvbuf, int len,int count); //客户请求处理函数
int main(int argc,char * argv[])
{
int listenFd=0;
//地址信息结构体大小
if ((listenFd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { //调用socket创建用于监听客户端的socket
std::cout<<"Creating socket failed."<<std::endl;
exit(1);
} int opt = SO_REUSEADDR;
setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); //设置socket属性 struct sockaddr_in serverAddr; //服务器地址信息结构体
bzero(&serverAddr,sizeof(serverAddr));
serverAddr.sin_family=AF_INET;
serverAddr.sin_port=htons(PORT);
serverAddr.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind(listenFd, (struct sockaddr *)&serverAddr, sizeof(struct sockaddr)) == -1) { //调用bind绑定地址
std::cout<<"Bind error."<<std::endl;
exit(1);
} if(listen(listenFd,BACKLOG) == -1) {
//调用listen开始监听
std::cout << "listen() error"<<std::endl;
exit(1);
} Client client[FD_SETSIZE]; //FD_SETSIZE为select函数支持的最大描述符个数
char recvbuf[MAXDATASIZE]; //缓冲区
int sin_size=sizeof(struct sockaddr_in);
//初始化select
int maxI;
int maxFd;
int sockfd;
int nReady;
ssize_t n;
fd_set readSet;//可读socket的文件描述符的集合
fd_set allSet;//所有socket的文件描述符的集合
for (int i = 0; i < FD_SETSIZE; i++) {
client[i].fd = -1;
}
maxFd= listenFd;
FD_ZERO(&allSet); //清空
FD_SET(listenFd, &allSet); //将监听socket加入select检测的描述符集合 int connectFd=0; //socket文件描述符
int clientCount=0;
while(1)
{
struct sockaddr_in addr;
readSet = allSet;
nReady = select(maxFd+1, &readSet, NULL,NULL, NULL); //调用select
if (FD_ISSET(listenFd, &readSet)) { //检测是否有新客户端请求
//调用accept,返回服务器与客户端连接的socket描述符
if ((connectFd = accept(listenFd,(struct sockaddr *)&addr,(socklen_t *)&sin_size))==-1) {
std::cout<<"accept() error"<<std::endl;
continue;
} //将新客户端的加入数组
int i = 0;
for (int i = 0; i < FD_SETSIZE; i++) {
if (client[i].fd < 0) {
client[i].fd = connectFd; //保存客户端描述符
char addrBuf[32];
sprintf(addrBuf,"%s:%d",inet_ntoa(addr.sin_addr),addr.sin_port);
clientCount++;
client[i].m_addr=std::string(addrBuf);
break;
}
}
if (i == FD_SETSIZE)
{
std::cout<<"too many clients"<<std::endl;
}
if (i > maxI) //数组最大元素值
{
maxI = i;
}
FD_SET(connectFd, &allSet); //将新socket连接放入select监听集合
if (connectFd > maxFd)
{
maxFd = connectFd; //确认maxfd是最大描述符
} if (--nReady <= 0)
{
continue; //如果没有新客户端连接,继续循环
}
} for (int i = 0; i <= maxI; i++)
{
if ( (sockfd = client[i].fd) < 0) //如果客户端描述符小于0,则没有客户端连接,检测下一个
{
continue;
}
if (FD_ISSET(sockfd, &readSet))
{ //检测此客户端socket是否有数据
int nReadLength = recv(sockfd, recvbuf, MAXDATASIZE,0);
if (nReadLength == 0)
{ //从客户端socket读数据,等于0表示网络中断
close(sockfd); //关闭socket连接
FD_CLR(sockfd, &allSet); //从监听集合中删除此socket连接
client[i].fd = -1; //数组元素设初始值,表示没客户端连接
std::cout<<"Client Addr: "<< client[i].m_addr << " Close "<<std::endl;
clientCount--;
}
else
{
process_cli(&client[i], recvbuf, nReadLength,clientCount); //接收到客户数据,开始处理
}
if (--nReady <= 0)
{
break; //如果没有新客户端有数据,跳出for循环回到while循环
}
}
}
}
close(listenFd); //关闭服务器监听socket
} void process_cli(Client *client, char* recvbuf, int len,int count)
{
char sendbuf[MAXDATASIZE];
OctArray16 * recvData = (OctArray16*)recvbuf;
std::cout<<"RecvData From Client:"<< client->m_addr <<" Data:"<<recvData->toString()<<std::endl;
sprintf(sendbuf,"%d--%s",count,GetCurrentTime().c_str());
OctArray16 sendData(sendbuf);
send(client->fd,&sendData,sendData.size(),0);
}
/* client */
#include <stdio.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <errno.h>
#include <stdlib.h>
#include <iostream>
#include "common.h" int main(int argc, char *argv[])
{
char hostname[100];
gethostname(hostname,sizeof(hostname));
int sockfd, numbytes; struct hostent *he;
struct sockaddr_in serv_addr;
if ((he = gethostbyname(defaultHostName)) == NULL)
{
std::cout<<"gethostbyname error!"<<std::endl;
return 0;;
}
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
std::cout<< "socket error!"<<std::endl;
return 0;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
serv_addr.sin_addr = *((struct in_addr *)he->h_addr);
bzero(&(serv_addr.sin_zero), 8);
if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr)) == -1)
{
std::cout<<"connect error!"<<std::endl;
return 0;
}
pid_t pId= getpid();
char SendBuf[16]; srand(time(0));
char buf[MAXDATASIZE];
for(int x = 0 ; x < 10 ; x++) {
sleep(rand()%10);
sprintf(SendBuf,"%d",pId);
OctArray16 sendData(SendBuf);
if ((numbytes = send(sockfd,&sendData,sendData.size(),0)) != -1)
{
if ((numbytes = read(sockfd, buf, MAXDATASIZE)) == -1)
{
std::cout<<"read error!\n"<<std::endl;
return 0;
}
OctArray16 * RecvData = (OctArray16*)buf;
std::cout<<"Client "<< pId <<" Recv: "<<RecvData->toString()<<std::endl;
}
}
close(sockfd);
}
/*common.h*/
#ifndef COMMON_H_
#define COMMON_H_
const int PORT=2248; //服务器端口
const int BACKLOG=5; //listen队列中等待的连接数
const int MAXDATASIZE=1024; //缓冲区大小
const char defaultHostName[] = "127.0.0.1";
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
#include <time.h>
#include <string.h>
struct Client { //客户端结构体
int fd; //客户端socket描述符
std::string m_addr;
};
class OctArray16 {
public:
uint32_t m_len;
char data[28];
size_t size(){
return 32;
}
std::string toString(){
return std::string(data,m_len);
} OctArray16(const char *str){
m_len = strlen(str);
strcpy(data,str);
}
}; std::string GetCurrentTime(){
time_t cutTime=time(0);
tm * tmT=localtime(&cutTime);
char buf[12];
sprintf(buf,"%d:%d:%d",tmT->tm_hour,tmT->tm_min,tmT->tm_sec);
return std::string(buf);
}
#endif
cmake_minimum_required(VERSION 2.8)

## Use the variable PROJECT_NAME for changing the target name
set( PROJECT_NAME "SelectLearn" ) ## Set our project name
project(${PROJECT_NAME}) ## Use all the *.cpp files we found under this folder for the project
SET(CLIENT_SOURCE Client.cpp common.h)
SET(SERVER_SOURCE Server.cpp common.h)
## Define the executable
add_executable(server ${SERVER_SOURCE})
add_executable(client ${CLIENT_SOURCE})

Linux 网络编程之 Select的更多相关文章

  1. Linux网络编程之select、poll、epoll的比较,以及epoll的水平触发(LT)和边缘触发(ET)

    Linux的网络通信先后推出了select.poll.epoll三种模式. select有以下三个问题: (1)每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大. ...

  2. linux网络编程之shutdown() 与 close()函数详解

    linux网络编程之shutdown() 与 close()函数详解 参考TCPIP网络编程和UNP: shutdown函数不能关闭套接字,只能关闭输入和输出流,然后发送EOF,假设套接字为A,那么这 ...

  3. (十)Linux 网络编程之ioctl函数

    1.介绍 Linux网络程序与内核交互的方法是通过ioctl来实现的,ioctl与网络协议栈进行交互,可得到网络接口的信息,网卡设备的映射属性和配置网络接口.并且还能够查看,修改,删除ARP高速缓存的 ...

  4. linux网络编程之socket编程(四)

    经过两周的等待,终于可以回归我正常的学习之旅了,表哥来北京了在我这暂住,晚上回家了基本在和他聊天,周末带他在北京城到处乱转,几乎剥夺了我自由学习的时间了,不过,亲人之情还是很难得的,工作学习并不是生活 ...

  5. linux网络编程之socket编程(六)

    经过一个国庆长假,又有一段时间没有写博文了,今天继续对linux网络编程进行学习,如今的北京又全面进入雾霾天气了,让我突然想到了一句名句:“真爱生活,珍惜生命”,好了,言归正传. 回顾一下我们之间实现 ...

  6. linux网络编程之posix条件变量

    今天来学习posix的最后一个相关知识----条件变量,言归正传. 下面用一个图来进一步描述条件变量的作用: 为什么呢? 这实际上可以解决生产者与消费者问题,而且对于缓冲区是无界的是一种比较理解的解决 ...

  7. linux/unix网络编程之 select

    转自http://www.cnblogs.com/zhuwbox/p/4221934.html linux 下的 select 知识点 unp 的第六章已经描述的很清楚,我们这里简单的说下 selec ...

  8. linux网络编程之IO模型

    本文转自作者:huangguisu 1. 概念理解 在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式:同步:      所谓 ...

  9. linux网络编程之socket编程(九)

    转眼又快到十一月份了,北京已经是完全进入冬天的节奏,外面冷风嗖嗖的,不过在夜深人静之时,学习永远成了我最快乐的时光,只有此时会觉得自己是如此踏实,虽说白天工作也是编一天程,但是此时的编程,是一种业余爱 ...

随机推荐

  1. 移动端H5混合开发设置复盘与总结

    此篇接上一篇: 移动端H5混合开发,Touch触控,拖拽,长按, 滑屏 实现方案 https://www.cnblogs.com/buoge/p/9346699.html app 场布设置已经上线了, ...

  2. iOS-Core Animation: 变换

    仿射变换 用 CGPoint 的每一列和 CGAffineTransform 矩阵的每一行对应元素相乘再求 和,就形成了一个新的 CGPoint 类型的结果.要解释一下图中显示的灰色元素, 为了能让矩 ...

  3. 【吴恩达课后测验】Course 1 - 神经网络和深度学习 - 第二周测验【中英】

    [中英][吴恩达课后测验]Course 1 - 神经网络和深度学习 - 第二周测验 第2周测验 - 神经网络基础 神经元节点计算什么? [ ]神经元节点先计算激活函数,再计算线性函数(z = Wx + ...

  4. MySQL 安装 用户管理 常用命令

    MySQL目录 数据库概览   数据库介绍 Why Choose MySQL MySQL的前世今生 MySQL的安装   Windows安装MySQL5.721 installer版 Windows安 ...

  5. [No0000122]Donet 中间语言,反编译 .net IL 指令速查

    名称 说明 Add 将两个值相加并将结果推送到计算堆栈上. Add.Ovf 将两个整数相加,执行溢出检查,并且将结果推送到计算堆栈上. Add.Ovf.Un 将两个无符号整数值相加,执行溢出检查,并且 ...

  6. tfidf_CountVectorizer 与 TfidfTransformer 保存和测试

    做nlp的时候,如果用到tf-idf,sklearn中用CountVectorizer与TfidfTransformer两个类,下面对和两个类进行讲解 一.训练以及测试 CountVectorizer ...

  7. 请运行TestStaticInitializeBlock.java示例,观察输出结果,总结出“静态初始化块的执行顺序”。

    答:执行顺序:静态初始化块->初始化块->构造函数 静态初始化块:在第一次加载类时执行,与对象的创建无关. 构造代码块:在调用构造方法时执行. 构造函数:在调用构造函数时执行.

  8. 分析SignalTap的仿真结果

    写在前面:本博客为本人原创,严禁任何形式的转载!本博客只允许放在博客园(.cnblogs.com),如果您在其他网站看到这篇博文,请通过下面这个唯一的合法链接转到原文! 本博客全网唯一合法URL:ht ...

  9. Page6:关于能控性、能观性、能测性及其判据(1)[Linear System Theory]

    内容包含能控性和能测性的定义,连续时间线性时不变系统能控性和能观测性判据

  10. flash cs4 如何新增自定义控件

    1. 新增控件脚本* import gfx.controls.CoreList; import gfx.core.UIComponent; import gfx.controls.CheckBox; ...