提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
一、多路io
1.select版本
在TCP中已知tcp获取地址
int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
a.服务器
#include "head.h"
int main(int argc, const char *argv[])
{
int listen_fd = socket(AF_INET,SOCK_STREAM,0);
if(-1 == listen_fd)
{
perror("listen_fd error");
return -1;
}
struct sockaddr_in ser,cli;
ser.sin_family = AF_INET;
ser.sin_port = htons(50000);
ser.sin_addr.s_addr = inet_addr("192.168.0.180");
int ret = bind(listen_fd,(SA)&ser,sizeof(ser));
if(-1 == ret)
{
perror("bind error");
return -1;
}
listen(listen_fd,3);
int len = sizeof(cli);
/*1.创建集合*/
fd_set temp_fd;
fd_set rd_set;
/*2.清空集合*/
FD_ZERO(&temp_fd);
FD_ZERO(&rd_set);
/*3.将监听套接字放入temp_fd集合中*/
FD_SET(listen_fd,&temp_fd);
int maxfd = listen_fd;
int i = 0;
int conn;
while(1)
{
/*5.清楚标志位*/
rd_set = temp_fd;
/*4.等待事件到来,监听套接字响应有客户端连接*/
select(maxfd+1,&rd_set,NULL,NULL,NULL);
/*i=listen_fd,不能从0开始*/
for(i=listen_fd;i<maxfd+1;++i)
{
/*6.处理事件*/
if(FD_ISSET(listen_fd,&rd_set) && i == listen_fd)
{
conn = accept(listen_fd,(SA)&cli,&len);
/*有新的客户端连接进行,将套接字放入待检测的集合中*/
FD_SET(conn,&temp_fd);
/*如果套接字最大描述符大则更新最大描述符*/
if(conn > maxfd)
{
maxfd = conn;
}
}
if(FD_ISSET(i,&rd_set) && i != listen_fd)
{
char buf[1024] = {0};
int ret_rd = recv(i,buf,sizeof(buf),0);
if(ret_rd <= 0)
{
/*有客户端连接离开,将套接字从待检测的集合中移除*/
FD_CLR(i,&temp_fd);
close(i);
}
time_t tm;
time(&tm);
sprintf(buf,"%s : %s",buf,ctime(&tm));
send(i,buf,strlen(buf),0);
}
}
}
close(conn);
close(listen_fd);
return 0;
}
b.客户端
#include "head.h"
int main(int argc, const char *argv[])
{
int conn = socket(AF_INET,SOCK_STREAM,0);
if(-1 == conn)
{
perror("conn error");
return -1;
}
struct sockaddr_in ser;
ser.sin_family = AF_INET;
ser.sin_port = htons(50000);
ser.sin_addr.s_addr = inet_addr("192.168.0.180");
connect(conn,(SA)&ser,sizeof(ser));
while(1)
{
char buf[1024] = {"this is tcp test "};
send(conn,buf,strlen(buf),0);
int ret_rd = recv(conn,buf,sizeof(buf),0);
if(ret_rd == -1)
{
break;
}
sleep(1);
printf(buf,"%s\n",buf);
}
close(conn);
return 0;
}
2.epoll版本
a.服务器
#include "head.h"
int add_ep(int ep_fd ,int fd)
{
struct epoll_event ev;
ev.data.fd = fd;
ev.events = EPOLLIN ;
int ret = epoll_ctl(ep_fd,EPOLL_CTL_ADD,fd,&ev);
if(-1 == ret)
{
perror("epoll_ctl error");
exit(1);
}
return 0;
}
int del_ep(int ep_fd,int fd)
{
struct epoll_event ev;
ev.data.fd = fd;
ev.events = EPOLLIN ;
int ret = epoll_ctl(ep_fd,EPOLL_CTL_DEL,fd,&ev);
if(-1 == ret)
{
perror("epoll_ctl error");
exit(1);
}
return 0;
}
int main(int argc, const char *argv[])
{
int listen_fd = socket(AF_INET,SOCK_STREAM,0);
if(-1 == listen_fd)
{
perror("listen_fd error");
return -1;
}
struct sockaddr_in ser,cli;
ser.sin_family = AF_INET;
ser.sin_port = htons(50000);
ser.sin_addr.s_addr = inet_addr("192.168.0.180");
int ret = bind(listen_fd,(SA)&ser,sizeof(ser));
if(-1 == ret)
{
perror("bind error");
return -1;
}
listen(listen_fd,3);
int len = sizeof(cli);
int conn ;
time_t tm;
/*1.创建事件结构体集合*/
int ep_fd = epoll_create(100);
/*2.向结合中添加关心的文件描述符*/
add_ep(ep_fd,listen_fd);
struct epoll_event rev[100];
int i =0;
while(1)
{
/*3.等待事件响应*/
int ret_ep = epoll_wait(ep_fd,rev,100,-1);
for(i=0;i<ret_ep;++i)
{
if(rev[i].data.fd == listen_fd)
{
conn = accept(listen_fd,(SA)&cli,&len);
/*4.将新来的客户端,添加到集合中*/
add_ep(ep_fd,conn);
}
if(rev[i].data.fd != listen_fd)
{
char buf[1024] = {0};
int conn = rev[i].data.fd;
int ret_rd = recv(conn,buf,sizeof(buf),0);
if(ret_rd <= 0)
{
/*5.若客户端离开,则将文件描述符从集合中删除*/
del_ep(ep_fd,conn);
close(conn);
}
time(&tm);
sprintf(buf,"%s : %s",buf,ctime(&tm));
send(conn,buf,strlen(buf),0);
}
}
}
close(conn);
close(listen_fd);
return 0;
}
b.客户端
#include "head.h"
int main(int argc, const char *argv[])
{
int conn = socket(AF_INET,SOCK_STREAM,0);
if(-1 == conn)
{
perror("conn error");
return -1;
}
struct sockaddr_in ser;
ser.sin_family = AF_INET;
ser.sin_port = htons(50000);
ser.sin_addr.s_addr = inet_addr("192.168.0.180");
connect(conn,(SA)&ser,sizeof(ser));
while(1)
{
char buf[1024] = {"this is tcp test "};
send(conn,buf,strlen(buf),0);
int ret_rd = recv(conn,buf,sizeof(buf),0);
if(ret_rd == -1)
{
break;
}
sleep(1);
printf(buf,"%s\n",buf);
}
close(conn);
return 0;
}
3.进程版本
a.服务器
#include "head.h"
/*信号处理函数,回收子进程空间*/
void handle(int num)
{
wait(NULL);
return ;
}
int main(int argc, const char *argv[])
{
signal(SIGCHLD,handle);
int listen_fd = socket(AF_INET,SOCK_STREAM,0);
if(-1 == listen_fd)
{
perror("listen_fd error");
return -1;
}
struct sockaddr_in ser,cli;
ser.sin_family = AF_INET;
ser.sin_port = htons(50000);
ser.sin_addr.s_addr = inet_addr("192.168.0.180");
int ret = bind(listen_fd,(SA)&ser,sizeof(ser));
if(-1 == ret)
{
perror("bind error");
return -1;
}
listen(listen_fd,3);
int len = sizeof(cli);
int conn;
while(1)
{
conn = accept(listen_fd,(SA)&cli,&len);
pid_t pid = fork();
if(pid < 0)
{
perror("fork error ");
return -1;
}
if(pid > 0 )
{
/*父进程中conn不使用,且发生了复制,将conn关闭,如果不关闭文件描述符累计到1023*/
close(conn);
}
else if(pid == 0)
{
/*子进程中不使用listen_fd,关闭监听套接字*/
close(listen_fd);
while(1)
{
char buf[1024] = {0};
int ret_rd = recv(conn,buf,sizeof(buf),0);
if(ret_rd <= 0)
{
close(conn);
exit(1);
}
time_t tm;
time(&tm);
sprintf(buf,"%s : %s",buf,ctime(&tm));
send(conn,buf,strlen(buf),0);
}
}
}
return 0;
}
b.客户端
#include "head.h"
int main(int argc, const char *argv[])
{
int conn = socket(AF_INET,SOCK_STREAM,0);
if(-1 == conn)
{
perror("conn error");
return -1;
}
struct sockaddr_in ser;
ser.sin_family = AF_INET;
ser.sin_port = htons(50000);
ser.sin_addr.s_addr = inet_addr("192.168.0.180");
connect(conn,(SA)&ser,sizeof(ser));
while(1)
{
char buf[1024] = {"this is tcp test "};
send(conn,buf,strlen(buf),0);
int ret_rd = recv(conn,buf,sizeof(buf),0);
if(ret_rd == -1)
{
break;
}
sleep(1);
printf(buf,"%s\n",buf);
}
close(conn);
return 0;
}
4.线程版本
a.服务器
#include "head.h"
void* thread(void *arg)
{
pthread_detach(pthread_self());
int conn = *(int*)arg;
while(1)
{
char buf[1024] = {0};
int ret_rd = recv(conn,buf,sizeof(buf),0);
if(ret_rd <= 0)
{
close(conn);
break;
}
time_t tm;
time(&tm);
sprintf(buf,"%s : %s",buf,ctime(&tm));
send(conn,buf,strlen(buf),0);
}
return NULL;
}
int main(int argc, const char *argv[])
{
int listen_fd = socket(AF_INET,SOCK_STREAM,0);
if(-1 == listen_fd)
{
perror("listen_fd error");
return -1;
}
struct sockaddr_in ser,cli;
ser.sin_family = AF_INET;
ser.sin_port = htons(50000);
ser.sin_addr.s_addr = inet_addr("192.168.0.180");
int ret = bind(listen_fd,(SA)&ser,sizeof(ser));
if(-1 == ret)
{
perror("bind error");
return -1;
}
listen(listen_fd,3);
int len = sizeof(cli);
int conn ;
while(1)
{
conn = accept(listen_fd,(SA)&cli,&len);
pthread_t tid ;
pthread_create(&tid,NULL,thread,&conn);
}
close(listen_fd);
return 0;
}
b.客户端
#include "head.h"
int main(int argc, const char *argv[])
{
int conn = socket(AF_INET,SOCK_STREAM,0);
if(-1 == conn)
{
perror("conn error");
return -1;
}
struct sockaddr_in ser;
ser.sin_family = AF_INET;
ser.sin_port = htons(50000);
ser.sin_addr.s_addr = inet_addr("192.168.0.180");
connect(conn,(SA)&ser,sizeof(ser));
while(1)
{
char buf[1024] = {"this is tcp test "};
send(conn,buf,strlen(buf),0);
int ret_rd = recv(conn,buf,sizeof(buf),0);
if(ret_rd == -1)
{
break;
}
sleep(1);
printf(buf,"%s\n",buf);
}
close(conn);
return 0;
}