1.多路IO
1.select
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
/* According to POSIX.1-2001, POSIX.1-2008 */
#include <sys/select.h>/* According to earlier standards */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
typedef struct sockaddr* (SA);
int main(int argc, char *argv[])
{//监听套接字int listfd = socket(AF_INET,SOCK_STREAM,0 );if(-1 ==listfd){perror("socket");exit(1);}struct sockaddr_in ser,cli;bzero(&ser,sizeof(ser));bzero(&cli,sizeof(cli));ser.sin_family = AF_INET;ser.sin_port = htons(50000);ser.sin_addr.s_addr =inet_addr("127.0.0.1");//man 7 socket int on = 1;setsockopt(listfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));setsockopt(listfd,SOL_SOCKET,SO_REUSEPORT,&on,sizeof(on));int ret = bind(listfd,(SA)&ser,sizeof(ser));if(-1 ==ret){perror("bind");exit(1);}//建立连接的排队数listen(listfd,3);socklen_t len = sizeof(cli);//1 create set fd_set rd_set,tmp_set;FD_ZERO(&rd_set);FD_ZERO(&tmp_set);//2.add fd FD_SET(listfd,&tmp_set);int maxfd = listfd;while(1){ rd_set = tmp_set;select(maxfd+1,&rd_set,NULL,NULL,NULL);int i = 0 ;//通讯套接字for(i = 0 ;i<maxfd+1;i++){if(FD_ISSET(i,&rd_set) && i ==listfd){int conn = accept(listfd,(SA)&cli,&len);if(-1 == conn){perror("accept");// exit(1);continue;}FD_SET(conn,&tmp_set);if(conn>maxfd)maxfd = conn;}if(FD_ISSET(i,&rd_set) && i!=listfd){int conn = i ;char buf[512]={0};int rd_ret = recv(conn,buf,sizeof(buf),0);if(rd_ret<=0){FD_CLR(conn,&tmp_set);close(conn);printf("cli offline\n");break;}//printf("cli:%s\n",buf);time_t tm;time(&tm);sprintf(buf,"%s %s",buf,ctime(&tm));send(conn,buf,strlen(buf),0);}}}close(listfd);return 0;
}
2.epoll
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>#include <sys/epoll.h>
typedef struct sockaddr* (SA);
int add_fd(int epfd,int fd)
{struct epoll_event ev;ev.events = EPOLLIN;ev.data.fd = fd;int ret = epoll_ctl(epfd,EPOLL_CTL_ADD,fd,&ev);if(-1 == ret){perror("add fd");}return ret;
}
int del_fd(int epfd,int fd)
{struct epoll_event ev;ev.events = EPOLLIN;ev.data.fd = fd;int ret = epoll_ctl(epfd,EPOLL_CTL_DEL,fd,&ev);if(-1 == ret){perror("add fd");}return ret;
}int main(int argc, char *argv[])
{//监听套接字int listfd = socket(AF_INET,SOCK_STREAM,0 );if(-1 ==listfd){perror("socket");exit(1);}struct sockaddr_in ser,cli;bzero(&ser,sizeof(ser));bzero(&cli,sizeof(cli));ser.sin_family = AF_INET;ser.sin_port = htons(50000);ser.sin_addr.s_addr =inet_addr("127.0.0.1");//man 7 socket int on = 1;setsockopt(listfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));setsockopt(listfd,SOL_SOCKET,SO_REUSEPORT,&on,sizeof(on));int ret = bind(listfd,(SA)&ser,sizeof(ser));if(-1 ==ret){perror("bind");exit(1);}//建立连接的排队数listen(listfd,3);socklen_t len = sizeof(cli);struct epoll_event rev[10]={0};//1 create set int epfd = epoll_create(10);if(-1 == epfd){perror("epoll_create");return 1;}// 2 .add fd add_fd(epfd,listfd);while(1){ //3 wait event int ep_ret = epoll_wait(epfd,rev,10,-1);int i = 0 ;//4 find fd handlefor(i = 0 ;i<ep_ret;i++){if(rev[i].data.fd == listfd){ //通讯套接字int conn = accept(listfd,(SA)&cli,&len);if(-1 == conn){perror("accept");continue;}add_fd(epfd,conn);}else {int conn = rev[i].data.fd;char buf[512]={0};int rd_ret = recv(conn,buf,sizeof(buf),0);if(rd_ret<=0){del_fd(epfd,conn);close(conn);break;}time_t tm;time(&tm);sprintf(buf,"%s %s",buf,ctime(&tm));send(conn,buf,strlen(buf),0);}}}close(listfd);return 0;
}
2.并发模型
1.进程
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
#include <signal.h>
#include <sys/wait.h>
typedef struct sockaddr* (SA);
void handle(int num)
{wait(NULL);
}
int main(int argc, char *argv[])
{signal(SIGCHLD,handle);//监听套接字int listfd = socket(AF_INET,SOCK_STREAM,0 );if(-1 ==listfd){perror("socket");exit(1);}struct sockaddr_in ser,cli;bzero(&ser,sizeof(ser));bzero(&cli,sizeof(cli));ser.sin_family = AF_INET;ser.sin_port = htons(50000);ser.sin_addr.s_addr =inet_addr("127.0.0.1");//man 7 socket int on = 1;setsockopt(listfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));setsockopt(listfd,SOL_SOCKET,SO_REUSEPORT,&on,sizeof(on));int ret = bind(listfd,(SA)&ser,sizeof(ser));if(-1 ==ret){perror("bind");exit(1);}//建立连接的排队数listen(listfd,3);socklen_t len = sizeof(cli);while(1){//通讯套接字int conn = accept(listfd,(SA)&cli,&len);if(-1 == conn){perror("accept");//exit(1);continue;}pid_t pid = fork();if(0 == pid){close(listfd);while(1){char buf[512]={0};int rd_ret = recv(conn,buf,sizeof(buf),0);if(rd_ret<=0){printf("cli off line\n");close(conn);//break;exit(1);}printf("cli:%s\n",buf);time_t tm;time(&tm);sprintf(buf,"%s %s",buf,ctime(&tm));send(conn,buf,strlen(buf),0);}}else if (pid>0){close(conn);}else{printf("fork");continue;}}close(listfd);return 0;
}
2.线程
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
#include <signal.h>
#include <sys/wait.h>
#include <pthread.h>
typedef struct sockaddr* (SA);void* th(void* arg)
{pthread_detach(pthread_self());int conn =* (int*)arg;//sem_post();while(1){char buf[512]={0};int rd_ret = recv(conn,buf,sizeof(buf),0);if(rd_ret<=0){printf("cli off line\n");close(conn);break;}printf("cli:%s\n",buf);time_t tm;time(&tm);sprintf(buf,"%s %s",buf,ctime(&tm));send(conn,buf,strlen(buf),0);}return NULL;
}
int main(int argc, char *argv[])
{//监听套接字int listfd = socket(AF_INET,SOCK_STREAM,0 );if(-1 ==listfd){perror("socket");exit(1);}struct sockaddr_in ser,cli;bzero(&ser,sizeof(ser));bzero(&cli,sizeof(cli));ser.sin_family = AF_INET;ser.sin_port = htons(50000);ser.sin_addr.s_addr =inet_addr("127.0.0.1");//man 7 socket int on = 1;setsockopt(listfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));setsockopt(listfd,SOL_SOCKET,SO_REUSEPORT,&on,sizeof(on));int ret = bind(listfd,(SA)&ser,sizeof(ser));if(-1 ==ret){perror("bind");exit(1);}//建立连接的排队数listen(listfd,3);socklen_t len = sizeof(cli);while(1){//通讯套接字int conn = accept(listfd,(SA)&cli,&len);if(-1 == conn){perror("accept");//exit(1);continue;}pthread_t tid;pthread_create(&tid,NULL,th,&conn);//sem_wait();// join();// 确保th中,把conn保存到局部变量中usleep(1000*5);}close(listfd);return 0;
}
3.循环
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>#define PORT 8888#define BUFFER_SIZE 1024int main() {int server_fd, new_socket;struct sockaddr_in address;int addrlen = sizeof(address);char buffer[BUFFER_SIZE] = {0};// 创建服务器套接字if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {perror("socket failed");exit(EXIT_FAILURE);}address.sin_family = AF_INET;address.sin_addr.s_addr = INADDR_ANY;address.sin_port = htons(PORT);// 绑定套接字到指定端口if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {perror("bind failed");exit(EXIT_FAILURE);}// 监听连接if (listen(server_fd, 3) < 0) {perror("listen failed");exit(EXIT_FAILURE);}while (1) {// 接受新的连接if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {perror("accept failed");exit(EXIT_FAILURE);}while (1) {int valread = read(new_socket, buffer, BUFFER_SIZE);if (valread <= 0) {break;}printf("Received from client: %s\n", buffer);send(new_socket, buffer, strlen(buffer), 0);memset(buffer, 0, BUFFER_SIZE);}close(new_socket);}return 0;}