阻塞IO 每来一个请求创建一个线程
#include <stdio.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <unistd.h>
#include <pthread.h>
#include <assert.h>
#define MAX_READ_LINE 10240
static void * client_callback(void *arg) {
int conn_fd = *(int *)arg;
char buff[MAX_READ_LINE] = {0};
int recv_len = recv(conn_fd, buff, MAX_READ_LINE, 0);
assert(recv_len > 0);
buff[recv_len] = '\0';
fprintf(stdout, "recv message from client: %s\n", buff);
close(conn_fd);
return NULL;
}
int main(void) {
struct sockaddr_in t_sockaddr;
memset(&t_sockaddr, 0, sizeof(t_sockaddr));
t_sockaddr.sin_family = AF_INET;
t_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
t_sockaddr.sin_port = htons(10008);
int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
assert(listen_fd > 0);
int ret = bind(listen_fd, (struct sockaddr *)&t_sockaddr, sizeof(t_sockaddr));
assert(ret != -1);
ret = listen(listen_fd, 1024);
assert(ret != -1);
while(1) {
int conn_fd = accept(listen_fd, (struct sockaddr*)NULL, NULL);
assert(conn_fd > 0);
pthread_t th_id;
ret = pthread_create(&th_id, NULL, client_callback, &conn_fd);
assert(ret == 0);
}
close(listen_fd);
return 0;
}
IO多路复用-select
#include <stdio.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#define BUFFER_LENGTH 1024
int main(void) {
int ret = -1;
int server_ip_port = 10008;
struct sockaddr_in t_sockaddr;
memset(&t_sockaddr, 0, sizeof(t_sockaddr));
t_sockaddr.sin_family = AF_INET;
t_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
t_sockaddr.sin_port = htons(server_ip_port);
int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
assert(listen_fd > 0);
ret = bind(listen_fd,(struct sockaddr *) &t_sockaddr,sizeof(t_sockaddr));
assert(ret != -1);
ret = listen(listen_fd, 1024);
assert(ret != -1);
fd_set rfds, rset;;
FD_ZERO(&rfds);
FD_SET(listen_fd, &rfds);
int max_fd = listen_fd;
while(1) {
rset = rfds;
int nready = select(max_fd + 1, &rset, NULL, NULL, NULL);
if (nready < 0) {
continue;
}
if (FD_ISSET(listen_fd, &rset)) {
struct sockaddr_in client_addr;
memset(&client_addr, 0, sizeof(struct sockaddr_in));
socklen_t client_len = sizeof(client_addr);
int client_fd = accept(listen_fd, (struct sockaddr*)&client_addr, &client_len);
if (client_fd <= 0) {
continue;
}
char str[INET_ADDRSTRLEN] = {0};
printf("recvived from %s at port %d, sockfd:%d, client_fd:%d\n", inet_ntop(AF_INET, &client_addr.sin_addr, str, sizeof(str)),
ntohs(client_addr.sin_port), listen_fd, client_fd);
if (max_fd == FD_SETSIZE) {
printf("client_fd --> out range\n");
break;
}
FD_SET(client_fd, &rset);
if (client_fd > max_fd) {
max_fd = client_fd;
}
printf("sockfd:%d, max_fd:%d, client_fd:%d\n", listen_fd, max_fd, client_fd);
if (--nready == 0) {
continue;
}
}
for (int i = listen_fd + 1;i <= max_fd; i++) {
if (FD_ISSET(i, &rset)) {
char buffer[BUFFER_LENGTH] = {0};
ret = recv(i, buffer, BUFFER_LENGTH, 0);
if (ret < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
printf("read all data");
}
FD_CLR(i, &rfds);
close(i);
} else if (ret == 0) {
printf(" disconnect %d\n", i);
FD_CLR(i, &rfds);
close(i);
break;
} else {
printf("Recv: %s, %d Bytes\n", buffer, ret);
}
if (--nready == 0) {
break;
}
}
}
}
close(listen_fd);
return 0;
}
epoll模型
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/epoll.h>
#define MAX_EVENT_NUMBER 1024
#define BUFFER_SIZE 10
int setnonblocking( int fd ) {
int old_option = fcntl( fd, F_GETFL );
int new_option = old_option | O_NONBLOCK;
fcntl( fd, F_SETFL, new_option );
return old_option;
}
void addfd( int epollfd, int fd, int enable_et ) {
struct epoll_event event;
event.data.fd = fd;
event.events = EPOLLIN;
if(enable_et) {
event.events |= EPOLLET;
}
epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event);
setnonblocking(fd);
}
void lt(struct epoll_event* events, int number, int epollfd, int listenfd ) {
char buf[ BUFFER_SIZE ];
for (int i = 0; i < number; i++) {
int sockfd = events[i].data.fd;
if ( sockfd == listenfd ) {
struct sockaddr_in client_address;
socklen_t client_addrlength = sizeof(client_address);
int connfd = accept(listenfd, (struct sockaddr*)&client_address, &client_addrlength);
addfd(epollfd, connfd, -1);
} else if (events[i].events & EPOLLIN) {
printf( "event trigger once\n" );
memset( buf, '\0', BUFFER_SIZE );
int ret = recv(sockfd, buf, BUFFER_SIZE-1, 0);
if(ret <= 0) {
close( sockfd );
continue;
}
printf("get %d bytes of content: %s\n", ret, buf);
} else {
printf("something else happened \n");
}
}
}
void et(struct epoll_event* events, int number, int epollfd, int listenfd ) {
char buf[BUFFER_SIZE];
for ( int i = 0; i < number; i++ ) {
int sockfd = events[i].data.fd;
if (sockfd == listenfd) {
struct sockaddr_in client_address;
socklen_t client_addrlength = sizeof(client_address);
int connfd = accept(listenfd, (struct sockaddr*)&client_address, &client_addrlength );
addfd(epollfd, connfd, 0);
} else if (events[i].events & EPOLLIN) {
printf("event trigger once\n");
while(1) {
memset(buf, '\0', BUFFER_SIZE);
int ret = recv(sockfd, buf, BUFFER_SIZE-1, 0);
if( ret < 0 ) {
if((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
printf( "read later\n" );
break;
}
close(sockfd);
break;
} else if (ret == 0) {
close(sockfd);
} else {
printf("get %d bytes of content: %s\n", ret, buf);
}
}
} else {
printf( "something else happened \n" );
}
}
}
int main(int argc, char* argv[]) {
if(argc <= 2) {
printf( "usage: ip_address port_number\n");
return 1;
}
const char* ip = argv[1];
int port = atoi(argv[2]);
int ret = 0;
struct sockaddr_in address;
bzero(&address, sizeof(address));
address.sin_family = AF_INET;
inet_pton(AF_INET, ip, &address.sin_addr);
address.sin_port = htons(port);
int listenfd = socket(PF_INET, SOCK_STREAM, 0);
assert(listenfd >= 0);
ret = bind(listenfd, (struct sockaddr*)&address, sizeof(address));
assert(ret != -1);
ret = listen(listenfd, 5);
assert(ret != -1);
struct epoll_event events[MAX_EVENT_NUMBER];
int epollfd = epoll_create(5);
assert(epollfd != -1);
addfd(epollfd, listenfd, 0);
while(1) {
int ret = epoll_wait(epollfd, events, MAX_EVENT_NUMBER, -1);
if(ret < 0) {
printf("epoll failure\n");
break;
}
lt(events, ret, epollfd, listenfd);
//et( events, ret, epollfd, listenfd );
}
close(listenfd);
return 0;
}