/*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. redis(一)--认识redis

    Redis官网对redis的定义是:“Redis is an open source, BSD licensed, advanced key-value cache and store”,可以看出,R ...

  2. python 中面向对象的概念

    原文 域和作用空间 本地域,函数域(nonlocal)和 全局域(global) def scope_test(): def do_local(): spam = "local spam&q ...

  3. Jwt 中 token应该存储到哪里?

    关于 token 的存储问题 JWT: csrf 攻击无法获取第三方的 cookie,而是直接使用 cookie进行查询的时候会自动携带 cookie. xss攻击通过代码注入可以获取 cookie. ...

  4. .Net Windows Service(服务) 调试安装及System.Timers.Timer 使用

    Windows Service(服务)  是运行在后台的进程 1.VS建立 Windows 服务(.NET Framework) 2.添加Timer 双击Service1.cs可以拖控件(System ...

  5. 在CentOS中安装arial字体

    验证码不能正常显示是因为 linux 没有字体 1. widonws下载字体文件到Linux windows的字体比较多,其字体文件位于 C:\WINDOWS\Fonts . 从其中copy相应的字体 ...

  6. 洛谷 P1059明明的随机数 & P1068分数线划定 & P1781宇宙总统

    题目:https://www.luogu.org/problemnew/show/P1059 思路:STL中的set使用. //#include<bits/stdc++.h> #inclu ...

  7. 蓝桥杯 入门训练 Fibonacci数列 解析

    问题描述 Fibonacci数列的递推公式为:Fn=Fn-1+Fn-2,其中F1=F2=1. 当n比较大时,Fn也非常大,现在我们想知道,Fn除以10007的余数是多少. 输入格式 输入包含一个整数n ...

  8. [No0000182]Parallel Programming with .NET-Partitioning in PLINQ

    Every PLINQ query that can be parallelized starts with the same step: partitioning.  Some queries ma ...

  9. [No000015D]【李笑来 笔记整理】个人商业模式升级

    提前知道地图对你到达目标是至关重要的. 比较女性与男性的成本:女性的成本更高(周期性激素分泌波动),所以不要再这个时候和女朋友较劲,她也是身不由己,当你知道这件事情之后,你就会试着去理解她. 下面这张 ...

  10. [No0000C5]VS2010删除空行

    VS2010删除空行,查找内容:^:b*$\n,替换为:,查找范围:当前文档,使用:正则表达式