/*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. js中parseInt和Number

    昨天在项目中遇到一个问题,有关字符串准换成数字的问题,具体如下: 页面中<input type="number" id="bankNum" ng-mode ...

  2. Flask web开发之路五

    Jinjia2模板 紧接着上篇博客,接下去写if条件判断和for循环遍历以及过滤器 if条件判断 主app文件代码: from flask import Flask,render_template a ...

  3. :eq

    匹配一个给定索引值的元素?只要在html页面每个元素都有索引值,相同的元素按html位置顺序从0开始往下排.给定索引值:给定一个html某个区域的元素的索引值,也是从0开始 不给区域就是从html从d ...

  4. ELK之elasticdump迁移es数据

    参考:https://www.cnblogs.com/resn/p/9082663.html elasticsearch部分查询语句 获取集群节点列表 curl "172.16.30.55: ...

  5. [No0000163]卷福、神秘博士和一群老戏骨表演群口相声:To be or not to be该咋念,简直高潮迭起

        'To be or not to be, that is the question',<哈姆雷特>中这句经典台词到底应该怎么念? 这是古今无数哈姆雷特演员最爱琢磨的问题,一千个人就 ...

  6. ASP_NET实现界面无刷新的DropdownList两级联动效果

    所谓DropdownList联动,也就是在选一个DropdownList的时候使另外一个DropdownList的内容更新(如选省份时显示所属城市),按常规的方法那就是在第一个DropdownList ...

  7. HZAU2018年十大阅读之星演讲稿

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

  8. Entity Framework 6如何进行导航属性的筛选(context.Msg.First(t=>t.Id==1).Include(t=>t.MsgDetail),筛选MsgDetail带条件)

    问题: https://q.cnblogs.com/q/98333/ Msg表(Id,Content,IsDel).内有 virtual ICollection<MsgDetail> Ms ...

  9. 转:CSS设置HTML元素的高度与宽度的各种情况总结

    1.元素不设宽度第一种情况:元素为文档流中元素<!-- 父元素宽度为100px --><div style="width:100px;">     < ...

  10. Feature如何解决参数数量不匹配

    问题描述: Feature 写了两个参数,匹配到Steps.Java,  文件只写了两个参数,但是两个参数都加了$ 符号. 而$ 又是结束的意思. 1一:Feature  用例