socket(); //设置套接字
bind(); //绑定服务器
listen(); //设置监听上限
fd_set reset, allset; //创建“读”监听集合
FD_ZERO (&allset); // 将“读”监听集合清空
FD_SET (lfd, &allset); //将lfd添加至读集合种.
while (1){
rest = allset; //保存读监听集合
ret = select (MAXFD+1, &rset, NULL, NULL, NULL); //监听文件描述符集合对应的事件,这里只监听“读”事件。
if (ret > 0) {
if (FD_ISSET (lfd, &rset)){
cfd = accept(); //建立连接,返回cfd
FD_SET (cfd, &allset); //将新的cfd描述符添加到读集合中
}
}
for (i = lfd + 1; i <= 最大文件描述符; i++){
FD_ISSET (i, &rset);
read ();
//用户自定义功能
write ();
}
}
selcet 解析
1)所需头文件:
#include
#include
#include
2)函数原型:
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set * exceptfds, struct timeval *timeout)
nfds:select监视的文件句柄数,视进程中打开的文件数而定,一般设为你要监视各文件中的最大文件号加一。(注:nfds并非一定表示监视的文件句柄数。官方文档仅指出nfds is the highest-numbered file descriptor in any of the three sets, plus 1. (可在linux环境中通过man select命令查得))
readfds:select监视的可读文件句柄集合。
writefds: select监视的可写文件句柄集合。
exceptfds:select监视的异常文件句柄集合。
timeout:本次select()的超时结束时间。设置为NULL时,select阻塞监听。
返回值:-1出错;等于0或大于0,返回监听集合中,满足对应事件的总数。
注意:第二、三、四参数,
3)优点
跨平台:windows、linux、macos、unix、类unix、mips…
4)缺点
①监听上限受文件描述符限制,最大1024.
②检测满足条件的fd,需要自己编码,编码难度不小。
1)socket() 创建socket。
2)connect() 与服务器建立连接。
3)write() 写数据到socket的写缓冲,将数据发送到服务器。
4)read() 读数据。
5)显示读取结果。
6)close() 关闭fd。
#include
#include
#include
#include
#include
#include
#include
#include "warp.h"
#define PORT 666 //端口
#define MAX_LISTEN 128 //监听上限
int main (void)
{
printf ("hello\n");
int lfd, cfd;
struct sockaddr_in ser_addr, clt_addr;
socklen_t addr_len;
char addr_buf[INET_ADDRSTRLEN];
lfd = Socket (AF_INET, SOCK_STREAM, 0); //创建套接字
int opt = 1;
setsockopt (lfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)); //端口复用
bzero (&ser_addr, sizeof (ser_addr)); //结构体清零
ser_addr.sin_family = AF_INET;
ser_addr.sin_addr.s_addr = htonl (INADDR_ANY);
ser_addr.sin_port = htons (PORT);
Bind (lfd, (struct sockaddr*)&ser_addr, sizeof (ser_addr)); //绑定服务器
printf ("host ip: %s\n", inet_ntop(AF_INET, &ser_addr.sin_addr, addr_buf, sizeof(addr_buf)));
Listen (lfd, MAX_LISTEN); //设置监听上限
fd_set rset, allset; //创建 读监听集合
int sockfd;
int client[FD_SETSIZE]; //用于记录连接成功的cfd
int maxfd;
int maxi;
int nready;
int i,n;
char buf[256] = {0};
int read_len;
FD_ZERO (&rset);
FD_ZERO (&allset);
FD_SET (lfd, &allset);
maxfd = lfd;
maxi = -1;
for (i=0; i<FD_SETSIZE; i++) //初始化为-1,表示全为空
client[i] = -1;
while (1)
{
rset = allset;
nready = select (maxfd + 1, &rset, NULL, NULL, NULL); //nready,接收满足对应读事件的总数.
if (nready < 0)
PERROR ("select");
if (FD_ISSET (lfd, &rset)) //判断是否有客户端请求连接
{
addr_len = sizeof (clt_addr);
cfd = Accept (lfd, (struct sockaddr*)&clt_addr, &addr_len); //这里的accept不会阻塞,因为有连接请求事件被触发,它才会进入此分支。
printf ("access network IP:%s prot:%d\n",
inet_ntop(AF_INET, &clt_addr.sin_addr,
addr_buf, sizeof(addr_buf)),
ntohs(clt_addr.sin_port));
for (i=0; i<FD_SETSIZE; i++) //寻找client的空位置
if (client[i] == -1) {
client[i] = cfd;
break;
}
if (i == FD_SETSIZE){ //如果满了(等于1024),提示错误,退出程序
fputs ("too many clients\n", stderr);
exit (1);
}
FD_SET (cfd, &allset);
if (cfd > maxfd)
maxfd = cfd;
if (i > maxi)
maxi = i;
if (--nready == 0) //如果满足事件数量为1,则返回select处继续等待事件;如果满足事件数量为大于1,则进行往下执行for循环,说明还有其它事件被触发。
continue;
}
for (i=0; i <= maxi; i++)
{
if ((sockfd = client[i]) < 0) //client为-1的不处理
continue;
if (FD_ISSET (sockfd, &rset)) //实现大小写转换
{
read_len = Read (sockfd, buf, sizeof(buf));
if (read_len == 0) //说明客户端断开
{
Close (sockfd);
FD_CLR (sockfd, &allset);
client[i] = -1;
}
else if (read_len > 0) //读到客户端发来的数据
{
for (n=0; n < read_len; n++)
buf[n] = toupper (buf[n]);
printf ("%s",buf);
memset (buf, '\0', sizeof (buf));
}
if (--nready == 0)
break;
}
}
}
Close (lfd);
return 0;
}
#include
#include
#include
#include
#include
#include
#include
#include
#include "warp.h"
#define SEVR_PORT 666
int main (void)
{
int cfd;
struct sockaddr_in serv_addr;
int count = 10;
char buf[1024] = {0};
cfd = Socket (AF_INET, SOCK_STREAM, 0);
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons (SEVR_PORT);
inet_pton (AF_INET, "127.0.0.1", &serv_addr.sin_addr.s_addr);
Connect (cfd, (struct sockaddr *)&serv_addr, sizeof (serv_addr));
while (count--)
{
int ret = 0 ;
write (cfd, "i love u\n", 9);
ret = read (cfd, buf, strlen (buf));
//write (STDOUT_FILENO, buf, ret);
printf ("%s", buf);
sleep (1);
}
close (cfd);
return 0;
}