网络编程
1、API函数封装
#ifndef __WRAP_H_
#define __WRAP_H_
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <strings.h>
void perr_exit(const char *s);
int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr);
int Bind(int fd, const struct sockaddr *sa, socklen_t salen);
int Connect(int fd, const struct sockaddr *sa, socklen_t salen);
int Listen(int fd, int backlog);
int Socket(int family, int type, int protocol);
ssize_t Read(int fd, void *ptr, size_t nbytes);
ssize_t Write(int fd, const void *ptr, size_t nbytes);
int Close(int fd);
ssize_t Readn(int fd, void *vptr, size_t n);
ssize_t Writen(int fd, const void *vptr, size_t n);
ssize_t my_read(int fd, char *ptr);
ssize_t Readline(int fd, void *vptr, size_t maxlen);
int tcp4bind(short port,const char *IP);
#endif
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <strings.h>
void perr_exit(const char *s){
perror(s);
exit(-1);
}
int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr){
int n;
again:
if ((n = accept(fd, sa, salenptr)) < 0) {
if ((errno == ECONNABORTED) || (errno == EINTR))
goto again;
else
perr_exit("accept error");
}
return n;
}
int Bind(int fd, const struct sockaddr *sa, socklen_t salen){
int n;
if ((n = bind(fd, sa, salen)) < 0)
perr_exit("bind error");
return n;
}
int Connect(int fd, const struct sockaddr *sa, socklen_t salen){
int n;
if ((n = connect(fd, sa, salen)) < 0)
perr_exit("connect error");
return n;
}
int Listen(int fd, int backlog){
int n;
if ((n = listen(fd, backlog)) < 0)
perr_exit("listen error");
return n;
}
int Socket(int family, int type, int protocol){
int n;
if ((n = socket(family, type, protocol)) < 0)
perr_exit("socket error");
return n;
}
ssize_t Read(int fd, void *ptr, size_t nbytes){
ssize_t n;
again:
if ( (n = read(fd, ptr, nbytes)) == -1) {
if (errno == EINTR)
goto again;
else
return -1;
}
return n;
}
ssize_t Write(int fd, const void *ptr, size_t nbytes){
ssize_t n;
again:
if ( (n = write(fd, ptr, nbytes)) == -1) {
if (errno == EINTR)
goto again;
else
return -1;
}
return n;
}
int Close(int fd){
int n;
if ((n = close(fd)) == -1)
perr_exit("close error");
return n;
}
ssize_t Readn(int fd, void *vptr, size_t n){
size_t nleft;
ssize_t nread;
char *ptr;
ptr = vptr;
nleft = n;
while (nleft > 0) {
if ((nread = read(fd, ptr, nleft)) < 0) {
if (errno == EINTR)
nread = 0;
else
return -1;
} else if (nread == 0)
break;
nleft -= nread;
ptr += nread;
}
return n - nleft;
}
ssize_t Writen(int fd, const void *vptr, size_t n){
size_t nleft;
ssize_t nwritten;
const char *ptr;
ptr = vptr;
nleft = n;
while (nleft > 0) {
if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
if (nwritten < 0 && errno == EINTR)
nwritten = 0;
else
return -1;
}
nleft -= nwritten;
ptr += nwritten;
}
return n;
}
static ssize_t my_read(int fd, char *ptr){
static int read_cnt;
static char *read_ptr;
static char read_buf[100];
if (read_cnt <= 0) {
again:
if ( (read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0) {
if (errno == EINTR)
goto again;
return -1;
} else if (read_cnt == 0)
return 0;
read_ptr = read_buf;
}
read_cnt--;
*ptr = *read_ptr++;
return 1;
}
ssize_t Readline(int fd, void *vptr, size_t maxlen){
ssize_t n, rc;
char c, *ptr;
ptr = vptr;
for (n = 1; n < maxlen; n++) {
if ( (rc = my_read(fd, &c)) == 1) {
*ptr++ = c;
if (c == '\n')
break;
} else if (rc == 0) {
*ptr = 0;
return n - 1;
} else
return -1;
}
*ptr = 0;
return n;
}
int tcp4bind(short port,const char *IP){
struct sockaddr_in serv_addr;
int lfd = Socket(AF_INET,SOCK_STREAM,0);
bzero(&serv_addr,sizeof(serv_addr));
if(IP == NULL){
serv_addr.sin_addr.s_addr = INADDR_ANY;
}else{
if(inet_pton(AF_INET,IP,&serv_addr.sin_addr.s_addr) <= 0){
perror(IP);
exit(1);
}
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
Bind(lfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));
return lfd;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "wrap.h"
int main(int argc,char *argv[])
{
int cfd = Socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in serv;
serv.sin_family = AF_INET;
serv.sin_port = htons(8888);
inet_pton(AF_INET, "127.0.0.1", &serv.sin_addr.s_addr);
Connect(cfd, (struct sockaddr *)&serv, sizeof(serv));
int n;
char buf[256];
while(1){
memset(buf, 0x00, sizeof(buf));
n = Read(STDIN_FILENO, buf, sizeof(buf));
Write(cfd, buf, sizeof(buf));
memset(buf, 0x00, sizeof(buf));
n = Read(cfd, buf, sizeof(buf));
if(n<=0){
printf("read error or server closed, n==[%d]\n", n);
break;
}
printf("n==[%d], buf==[%s]\n", n, buf);
}
close(cfd);
return 0;
}
2、多进程版的网络服务器
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <signal.h>
#include <sys/wait.h>
#include <ctype.h>
#include "wrap.h"
void waitchild(int signo){
pid_t wpid;
while(1){
wpid = waitpid(-1, NULL, WNOHANG);
if(wpid>0){
printf("child exit, wpid==[%d]\n", wpid);
}
else if(wpid==0 || wpid==-1){
break;
}
}
}
int main()
{
int lfd = Socket(AF_INET, SOCK_STREAM, 0);
int opt = 1;
setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));
struct sockaddr_in serv;
serv.sin_family = AF_INET;
serv.sin_port = htons(8888);
serv.sin_addr.s_addr = htonl(INADDR_ANY);
Bind(lfd, (struct sockaddr *)&serv, sizeof(serv));
Listen(lfd, 128);
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, SIGCHLD);
sigprocmask(SIG_BLOCK, &mask, NULL);
int cfd;
socklen_t len;
char sIP[16];
pid_t pid;
struct sockaddr_in client;
while(1){
memset(sIP, 0x00, sizeof(sIP));
len = sizeof(client);
bzero(&client, sizeof(client));
cfd = Accept(lfd, (struct sockaddr *)&client, &len);
printf("client-->[%s]:[%d]\n", inet_ntop(AF_INET, &client.sin_addr.s_addr, sIP, sizeof(sIP)), ntohs(client.sin_port));
pid = fork();
if(pid<0){
perror("fork error");
close(lfd);
return -1;
}
else if(pid>0)
{
close(cfd);
struct sigaction act;
act.sa_handler = waitchild;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
sigaction(SIGCHLD, &act, NULL);
sigprocmask(SIG_UNBLOCK, &mask, NULL);
}
else if(pid==0)
{
close(lfd);
int i = 0;
int n = 0;
char buf[1024];
while(1){
memset(buf, 0x00, sizeof(buf));
n = Read(cfd, buf, sizeof(buf));
if(n<=0) {
printf("read error or client closed, n==[%d]\n", n);
break;
}
printf("read over, n==[%d],buf==[%s]\n", n, buf);
for(i=0; i<n; i++){
buf[i] = toupper(buf[i]);
}
write(cfd, buf, n);
}
close(cfd);
exit(0);
}
}
close(lfd);
return 0;
}
3、多线程版本的服务器
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <ctype.h>
#include <pthread.h>
#include "wrap.h"
typedef struct info{
int cfd;
int idx;
pthread_t thread;
struct sockaddr_in client;
}INFO;
INFO thInfo[1024];
void *thread_work(void *arg){
INFO *p = (INFO *)arg;
printf("idx==[%d]\n", p->idx);
char sIP[16];
memset(sIP, 0x00, sizeof(sIP));
printf("new client:[%s][%d]\n", inet_ntop(AF_INET, &(p->client.sin_addr.s_addr), sIP, sizeof(sIP)), ntohs(p->client.sin_port));
int n;
int cfd = p->cfd;
struct sockaddr_in client;
memcpy(&client, &(p->client), sizeof(client));
char buf[1024];
while(1){
memset(buf, 0x00, sizeof(buf));
n = Read(cfd, buf, sizeof(buf));
if(n<=0){
printf("read error or client closed, n==[%d]\n", n);
Close(cfd);
p->cfd =-1;
pthread_exit(NULL);
}
for(int i=0; i<n; i++){
buf[i] = toupper(buf[i]);
}
Write(cfd, buf, n);
}
}
void init_thInfo(){
int i = 0;
for(i=0; i<1024; i++){
thInfo[i].cfd = -1;;
}
}
int findIndex(){
int i;
for(i=0; i<1024; i++){
if(thInfo[i].cfd==-1){
break;
}
}
if(i==1024){
return -1;
}
return i;
}
int main()
{
int lfd = Socket(AF_INET, SOCK_STREAM, 0);
int opt = 1;
setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));
struct sockaddr_in serv;
bzero(&serv, sizeof(serv));
serv.sin_family = AF_INET;
serv.sin_port = htons(8888);
serv.sin_addr.s_addr = htonl(INADDR_ANY);
Bind(lfd, (struct sockaddr *)&serv, sizeof(serv));
Listen(lfd, 128);
init_thInfo();
int cfd;
int ret;
int idx;
socklen_t len;
pthread_t thread;
struct sockaddr_in client;
while(1){
len = sizeof(client);
bzero(&client, sizeof(client));
cfd = Accept(lfd, (struct sockaddr *)&client, &len);
idx = findIndex();
if(idx==-1){
Close(cfd);
continue;
}
thInfo[idx].cfd = cfd;
thInfo[idx].idx = idx;
memcpy(&thInfo[idx].client, &client, sizeof(client));
ret = pthread_create(&thInfo[idx].thread, NULL, thread_work, &thInfo[idx]);
if(ret!=0){
printf("create thread error:[%s]\n", strerror(ret));
exit(-1);
}
pthread_detach(thInfo[idx].thread);
}
Close(lfd);
return 0;
}
4、select网络服务器
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <ctype.h>
#include <signal.h>
#include <sys/wait.h>
#include "wrap.h"
int main(int argc,char *argv[])
{
int lfd = Socket(AF_INET, SOCK_STREAM, 0);
int opt = 1;
setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));
struct sockaddr_in serv;
serv.sin_family = AF_INET;
serv.sin_port = htons(8888);
serv.sin_addr.s_addr = htonl(INADDR_ANY);
bind(lfd, (struct sockaddr *)&serv, sizeof(serv));
Listen(lfd, 128);
fd_set readfds;
fd_set tmpfds;
FD_ZERO(&readfds);
FD_ZERO(&tmpfds);
FD_SET(lfd, &readfds);
int nready;
int maxfd = lfd;
int cfd;
int i;
int sockfd;
int n;
char buf[1024];
char sIP[16];
socklen_t len;
struct sockaddr_in client;
while(1)
{
tmpfds = readfds;
nready = select(maxfd+1, &tmpfds, NULL,NULL, NULL);
if(nready<0)
{
if(errno==EINTR)
{
continue;
}
break;
}
if(FD_ISSET(lfd, &tmpfds))
{
memset(sIP, 0x00, sizeof(sIP));
len = sizeof(client);
bzero(&client, sizeof(client));
cfd = Accept(lfd, (struct sockaddr *)&client, &len);
printf("client:[%s] [%d]\n", inet_ntop(AF_INET, &(client.sin_addr.s_addr), sIP, sizeof(sIP)), ntohs(client.sin_port));
FD_SET(cfd, &readfds);
if(maxfd<cfd)
{
maxfd = cfd;
}
if(--nready==0)
{
continue;
}
}
for(i=lfd+1; i<=maxfd; i++)
{
sockfd = i;
if(FD_ISSET(sockfd, &tmpfds))
{
memset(buf, 0x00, sizeof(buf));
n = Read(sockfd, buf, sizeof(buf));
if(n<=0)
{
close(sockfd);
FD_CLR(sockfd, &readfds);
}
else
{
memset(sIP, 0x00, sizeof(sIP));
printf("client:[%s] [%d], buf==[%s]\n", inet_ntop(AF_INET, &(client.sin_addr.s_addr), sIP, sizeof(sIP)), ntohs(client.sin_port), buf);
int k;
for(k=0; k<n; k++)
{
buf[k] = toupper(buf[k]);
}
Write(sockfd, buf, n);
}
if(--nready==0)
{
break;
}
}
}
}
close(lfd);
return 0;
}
5、poll网络服务器
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>
#include <poll.h>
#include <ctype.h>
#include "wrap.h"
int main(int argc,char *argv[])
{
int lfd = Socket(AF_INET, SOCK_STREAM, 0);
int opt = 1;
setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));
struct sockaddr_in serv;
serv.sin_family = AF_INET;
serv.sin_port = htons(8888);
serv.sin_addr.s_addr = htonl(INADDR_ANY);
bind(lfd, (struct sockaddr *)&serv, sizeof(serv));
Listen(lfd, 128);
struct pollfd client[1024];
int i;
for(i=0; i<1024; i++)
{
client[i].fd = -1;
}
client[0].fd = lfd;
client[0].events = POLLIN;
int nready;
int maxfd = 0;
int cfd;
int sockfd;
int n;
char buf[1024];
char sIP[16];
socklen_t len;
struct sockaddr_in clit;
while(1)
{
nready = poll(client, maxfd+1, -1);
if(nready<0)
{
if(errno==EINTR)
{
continue;
}
break;
}
if(client[0].fd==lfd && (client[0].revents & POLLIN))
{
memset(sIP, 0x00, sizeof(sIP));
len = sizeof(clit);
bzero(&clit, sizeof(clit));
cfd = Accept(lfd, (struct sockaddr *)&clit, &len);
printf("client:[%s] [%d]\n", inet_ntop(AF_INET, &(clit.sin_addr.s_addr), sIP, sizeof(sIP)), ntohs(clit.sin_port));
for(i=1; i<1024; i++)
{
if(client[i].fd==-1)
{
client[i].fd = cfd;
client[i].events = POLLIN;
break;
}
}
if(i==1024)
{
close(cfd);
continue;
}
if(maxfd<i)
{
maxfd = i;
}
if(--nready==0)
{
continue;
}
}
for(i=1; i<=maxfd; i++)
{
if(client[i].fd==-1)
{
continue;
}
if(client[i].revents==POLLIN)
{
sockfd = client[i].fd;
memset(buf, 0x00, sizeof(buf));
n = Read(sockfd, buf, sizeof(buf));
if(n<=0)
{
printf("read error or client closed ,n==[%d]\n", n);
close(sockfd);
client[i].fd = -1;
}
else
{
memset(sIP, 0x00, sizeof(sIP));
printf("client:[%s] [%d], buf==[%s]\n", inet_ntop(AF_INET, &(clit.sin_addr.s_addr), sIP, sizeof(sIP)), ntohs(clit.sin_port), buf);
int k;
for(k=0; k<n; k++)
{
buf[k] = toupper(buf[k]);
}
Write(sockfd, buf, n);
}
if(--nready==0)
{
break;
}
}
}
}
close(lfd);
return 0;
}
6、epoll网络服务器
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>
#include <sys/epoll.h>
#include <ctype.h>
#include <fcntl.h>
#include "wrap.h"
int main(int argc,char *argv[])
{
int lfd = Socket(AF_INET, SOCK_STREAM, 0);
int opt = 1;
setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));
struct sockaddr_in serv;
serv.sin_family = AF_INET;
serv.sin_port = htons(8888);
serv.sin_addr.s_addr = htonl(INADDR_ANY);
bind(lfd, (struct sockaddr *)&serv, sizeof(serv));
Listen(lfd, 128);
int epfd = epoll_create(1024);
if(epfd<0)
{
perror("eprll_create error");
close(lfd);
return -1;
}
struct epoll_event ev;
ev.data.fd = lfd;
ev.events = EPOLLIN;
epoll_ctl(epfd, EPOLL_CTL_ADD, lfd, &ev);
int nready;
int cfd;
int sockfd;
int n;
int i;
char buf[1024];
char sIP[16];
socklen_t len;
memset(sIP, 0x00, sizeof(sIP));
struct sockaddr_in client;
bzero(&client, sizeof(client));
struct epoll_event events[1024];
while(1)
{
nready = epoll_wait(epfd, events, 1024, -1);
if(nready<0)
{
perror("epoll_wait error");
if(errno==EINTR)
{
continue;
}
break;
}
for(i=0; i<nready; i++)
{
len = sizeof(client);
sockfd = events[i].data.fd;
if(sockfd==lfd)
{
cfd = Accept(lfd, (struct sockaddr *)&client, &len);
printf("client:[%s] [%d]\n", inet_ntop(AF_INET, (struct sockaddr *)&client.sin_addr.s_addr, sIP, sizeof(sIP)), ntohs(client.sin_port));
ev.data.fd = cfd;
ev.events = EPOLLIN | EPOLLET;
epoll_ctl(epfd, EPOLL_CTL_ADD, cfd, &ev);
int flags = fcntl(cfd, F_GETFL, 0);
flags |= O_NONBLOCK;
fcntl(cfd, F_SETFL, flags);
continue;
}
while(1)
{
memset(buf, 0x00, sizeof(buf));
n = Read(sockfd, buf, 2);
if(n==-1)
{
printf("read over, n==[%d]\n",n);
break;
}
if(n==0 || (n<0 && n!=-1))
{
printf("n==[%d], buf==[%s]\n", n, buf);
Close(sockfd);
epoll_ctl(epfd, EPOLL_CTL_DEL, sockfd, NULL);
break;
}
else
{
printf("client:[%s] [%d], [%s]\n", inet_ntop(AF_INET, (struct sockaddr *)&client.sin_addr.s_addr, sIP, sizeof(sIP)), ntohs(client.sin_port), buf);
int k = 0;
for(k=0; k<n; k++)
{
buf[k] = toupper(buf[k]);
}
Write(sockfd, buf, n);
}
}
}
}
Close(epfd);
Close(lfd);
return 0;
}
7、epoll反应堆网络服务器
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/epoll.h>
#include <ctype.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "wrap.h"
#define BUF_LEN 1024
#define EVENT_SIZE 1024
int gepfd = 0;
void readdata(int fd, int events, void *arg);
typedef struct Event
{
int fd;
int events;
void (*call_back)(int fd, int events, void *arg);
void *arg;
char buf[1024];
int buflen;
int epfd;
}xevent;
xevent myevents[EVENT_SIZE+1];
void eventadd(int fd, int events, void (*call_back)(int, int, void *), void *arg, xevent *ev)
{
ev->fd = fd;
ev->events = events;
ev->arg = arg;
ev->call_back = call_back;
struct epoll_event epv;
epv.events = events;
epv.data.ptr = ev;
epoll_ctl(gepfd, EPOLL_CTL_ADD, fd, &epv);
}
void eventset(int fd, int events, void (*call_back)(int, int, void *), void *arg, xevent *ev)
{
ev->fd = fd;
ev->events = events;
ev->arg = arg;
ev->call_back = call_back;
struct epoll_event epv;
epv.events = events;
epv.data.ptr = ev;
epoll_ctl(gepfd, EPOLL_CTL_MOD, fd, &epv);
}
void eventdel(xevent *ev, int fd, int events)
{
printf("begin call %s\n", __FUNCTION__);
ev->fd = 0;
ev->events = 0;
ev->call_back = NULL;
memset(ev->buf, 0x00, sizeof(ev->buf));
ev->buflen = 0;
struct epoll_event epv;
epv.data.ptr = NULL;
epv.events = events;
epoll_ctl(gepfd, EPOLL_CTL_DEL, fd, &epv);
}
void senddata(int fd, int events, void *arg)
{
printf("begin call %s\n", __FUNCTION__);
xevent *ev = arg;
Write(fd, ev->buf, ev->buflen);
eventset(fd, EPOLLIN, readdata, arg, ev);
}
void readdata(int fd, int events, void *arg)
{
printf("begin call %s\n", __FUNCTION__);
xevent *ev = arg;
ev->buflen = Read(fd, ev->buf, sizeof(ev->buf));
if(ev->buflen>0)
{
eventset(fd, EPOLLOUT, senddata, arg, ev);
printf("n==[%d] buf==[%s]\n", ev->buflen, ev->buf);
int i = 0;
for(i=0; i<ev->buflen; i++)
{
ev->buf[i] = toupper(ev->buf[i]);
}
}
else if(ev->buflen==0)
{
Close(fd);
eventdel(ev, fd, EPOLLIN);
}
}
void initAccept(int fd, int events, void *arg)
{
printf("begin call %s, grep==%d\n", __FUNCTION__, gepfd);
int i;
struct sockaddr_in client;
char sIP[16];
memset(sIP, 0x00, sizeof(sIP));
bzero(&client, sizeof(client));
socklen_t len = sizeof(client);
int cfd = Accept(fd, (struct sockaddr *)&client, &len);
printf("client:[%s] [%d]\n",inet_ntop(AF_INET, (struct soctaddr *)&client.sin_addr.s_addr, sIP, sizeof(sIP)), ntohs(client.sin_port));
for(i=0; i<EVENT_SIZE; i++)
{
if(myevents[i].fd = 0)
{
break;
}
}
eventadd(cfd, EPOLLIN, readdata, &myevents[i], &myevents[i]);
}
int main(int argc,char *argv[])
{
int lfd = Socket(AF_INET, SOCK_STREAM, 0);
int opt = 1;
setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));
struct sockaddr_in serv;
serv.sin_family = AF_INET;
serv.sin_port = htons(8888);
serv.sin_addr.s_addr = htonl(INADDR_ANY);
bind(lfd, (struct sockaddr *)&serv, sizeof(serv));
Listen(lfd, 128);
gepfd = epoll_create(1024);
if(gepfd<0)
{
perror("eprll_create error");
close(lfd);
return -1;
}
printf("gepfd==[%d]\n", gepfd);
struct epoll_event events[1024];
eventadd(lfd, EPOLLIN, initAccept, &myevents[EVENT_SIZE], &myevents[EVENT_SIZE]);
while(1)
{
int nready = epoll_wait(gepfd, events, 1024, -1);
if(nready<0)
{
perr_exit("epoll_wait error");
}
else if(nready>0)
{
int i = 0;
for(i=0; i<nready; i++)
{
xevent *xe = events[i].data.ptr;
printf("fd==%d\n", xe->fd);
if(xe->events & events[i].events)
{
xe->call_back(xe->fd, xe->events, xe);
}
}
}
}
Close(lfd);
return 0;
}
8、udp通信
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <ctype.h>
int main(int argc,char *argv[])
{
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sockfd<0)
{
perror("socket error");
return -1;
}
struct sockaddr_in serv;
serv.sin_family = AF_INET;
serv.sin_port = htons(8888);
serv.sin_addr.s_addr = htonl(INADDR_ANY);
bind(sockfd, (struct sockaddr *)&serv, sizeof(serv));
int n;
char sIP[16];
char buf[1024];
socklen_t len;
struct sockaddr_in client;
while(1)
{
len = sizeof(client);
memset(sIP, 0x00, sizeof(sIP));
memset(buf, 0x00, sizeof(buf));
bzero(&client, sizeof(client));
n = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&client, &len);
printf("client:[%s] [%d]\n", inet_ntop(AF_INET, &client.sin_addr.s_addr, sIP, sizeof(sIP)), ntohs(client.sin_port));
if(n<0)
{
printf("recvfrom error, n==[%d]\n", n);
continue;
}
if(n==0)
{
printf("no data recvied, n==[%d]\n", n);
continue;
}
else if(n>0)
{
printf("n==[%d], buf==[%s]\n", n, buf);
len = sizeof(client);
int i;
for(i=0; i<n; i++)
{
buf[i] = toupper(buf[i]);
}
sendto(sockfd, buf, n, 0, (struct sockaddr *)&client, len);
}
}
close(sockfd);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int main(int argc,char *argv[])
{
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sockfd<0)
{
perror("socket error");
return -1;
}
struct sockaddr_in serv;
serv.sin_family = AF_INET;
serv.sin_port = htons(8888);
inet_pton(AF_INET, "127.0.0.1", &serv.sin_addr.s_addr);
int n;
char sIP[16];
char buf[1024];
socklen_t len;
struct sockaddr_in client;
while(1)
{
memset(buf, 0x00, sizeof(buf));
n = read(STDIN_FILENO, buf, sizeof(buf));
sendto(sockfd,buf, n, 0, (struct sockaddr *)&serv, sizeof(serv));
memset(buf, 0x00, sizeof(buf));
n = recvfrom(sockfd, buf, sizeof(buf), 0, NULL, NULL);
printf("n==[%d] [%s]\n", n, buf);
}
close(sockfd);
return 0;
}
9、线程池
#ifndef _THREADPOOL_H
#define _THREADPOOL_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
typedef struct _PoolTask
{
int tasknum;
void *arg;
void (*task_func)(void *arg);
}PoolTask ;
typedef struct _ThreadPool
{
int max_job_num;
int job_num;
PoolTask *tasks;
int job_push;
int job_pop;
int thr_num;
pthread_t *threads;
int shutdown;
pthread_mutex_t pool_lock;
pthread_cond_t empty_task;
pthread_cond_t not_empty_task;
}ThreadPool;
void create_threadpool(int thrnum,int maxtasknum);
void destroy_threadpool(ThreadPool *pool);
void addtask(ThreadPool *pool);
void taskRun(void *arg);
#endif
#include "threadpoolsimple.h"
ThreadPool *thrPool = NULL;
int beginnum = 1000;
void *thrRun(void *arg)
{
ThreadPool *pool = (ThreadPool*)arg;
int taskpos = 0;
PoolTask *task = (PoolTask *)malloc(sizeof(PoolTask));
while(1)
{
pthread_mutex_lock(&thrPool->pool_lock);
while(thrPool->job_num <= 0 && !thrPool->shutdown )
{
pthread_cond_wait(&thrPool->not_empty_task,&thrPool->pool_lock);
}
if(thrPool->job_num)
{
taskpos = (thrPool->job_pop++)%thrPool->max_job_num;
memcpy(task,&thrPool->tasks[taskpos],sizeof(PoolTask));
task->arg = task;
thrPool->job_num--;
pthread_cond_signal(&thrPool->empty_task);
}
if(thrPool->shutdown)
{
pthread_mutex_unlock(&thrPool->pool_lock);
free(task);
pthread_exit(NULL);
}
pthread_mutex_unlock(&thrPool->pool_lock);
task->task_func(task->arg);
}
}
void create_threadpool(int thrnum,int maxtasknum)
{
printf("begin call %s-----\n",__FUNCTION__);
thrPool = (ThreadPool*)malloc(sizeof(ThreadPool));
thrPool->thr_num = thrnum;
thrPool->max_job_num = maxtasknum;
thrPool->shutdown = 0;
thrPool->job_push = 0;
thrPool->job_pop = 0;
thrPool->job_num = 0;
thrPool->tasks = (PoolTask*)malloc((sizeof(PoolTask)*maxtasknum));
pthread_mutex_init(&thrPool->pool_lock,NULL);
pthread_cond_init(&thrPool->empty_task,NULL);
pthread_cond_init(&thrPool->not_empty_task,NULL);
int i = 0;
thrPool->threads = (pthread_t *)malloc(sizeof(pthread_t)*thrnum);
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
for(i = 0;i < thrnum;i++)
{
pthread_create(&thrPool->threads[i],&attr,thrRun,(void*)thrPool);
}
}
void destroy_threadpool(ThreadPool *pool)
{
pool->shutdown = 1;
pthread_cond_broadcast(&pool->not_empty_task);
int i = 0;
for(i = 0; i < pool->thr_num ; i++)
{
pthread_join(pool->threads[i],NULL);
}
pthread_cond_destroy(&pool->not_empty_task);
pthread_cond_destroy(&pool->empty_task);
pthread_mutex_destroy(&pool->pool_lock);
free(pool->tasks);
free(pool->threads);
free(pool);
}
void addtask(ThreadPool *pool)
{
pthread_mutex_lock(&pool->pool_lock);
while(pool->max_job_num <= pool->job_num)
{
pthread_cond_wait(&pool->empty_task,&pool->pool_lock);
}
int taskpos = (pool->job_push++)%pool->max_job_num;
pool->tasks[taskpos].tasknum = beginnum++;
pool->tasks[taskpos].arg = (void*)&pool->tasks[taskpos];
pool->tasks[taskpos].task_func = taskRun;
pool->job_num++;
pthread_mutex_unlock(&pool->pool_lock);
pthread_cond_signal(&pool->not_empty_task);
}
void taskRun(void *arg)
{
PoolTask *task = (PoolTask*)arg;
int num = task->tasknum;
printf("task %d is runing %lu\n",num,pthread_self());
sleep(1);
printf("task %d is done %lu\n",num,pthread_self());
}
int main()
{
create_threadpool(3,20);
int i = 0;
for(i = 0;i < 50 ; i++)
{
addtask(thrPool);
}
sleep(20);
destroy_threadpool(thrPool);
return 0;
}
10、web服务器
#ifndef _PUB_H
#define _PUB_H
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <strings.h>
#include <ctype.h>
char *get_mime_type(char *name);
int get_line(int sock, char *buf, int size);
int hexit(char c);
void strencode(char* to, size_t tosize, const char* from);
void strdecode(char *to, char *from);
#endif
#include "pub.h"
char *get_mime_type(char *name)
{
char* dot;
dot = strrchr(name, '.');
if (dot == (char*)0)
return "text/plain; charset=utf-8";
if (strcmp(dot, ".html") == 0 || strcmp(dot, ".htm") == 0)
return "text/html; charset=utf-8";
if (strcmp(dot, ".jpg") == 0 || strcmp(dot, ".jpeg") == 0)
return "image/jpeg";
if (strcmp(dot, ".gif") == 0)
return "image/gif";
if (strcmp(dot, ".png") == 0)
return "image/png";
if (strcmp(dot, ".css") == 0)
return "text/css";
if (strcmp(dot, ".au") == 0)
return "audio/basic";
if (strcmp( dot, ".wav") == 0)
return "audio/wav";
if (strcmp(dot, ".avi") == 0)
return "video/x-msvideo";
if (strcmp(dot, ".mov") == 0 || strcmp(dot, ".qt") == 0)
return "video/quicktime";
if (strcmp(dot, ".mpeg") == 0 || strcmp(dot, ".mpe") == 0)
return "video/mpeg";
if (strcmp(dot, ".vrml") == 0 || strcmp(dot, ".wrl") == 0)
return "model/vrml";
if (strcmp(dot, ".midi") == 0 || strcmp(dot, ".mid") == 0)
return "audio/midi";
if (strcmp(dot, ".mp3") == 0)
return "audio/mpeg";
if (strcmp(dot, ".ogg") == 0)
return "application/ogg";
if (strcmp(dot, ".pac") == 0)
return "application/x-ns-proxy-autoconfig";
return "text/plain; charset=utf-8";
}
int get_line(int sock, char *buf, int size)
{
int i = 0;
char c = '\0';
int n;
while ((i < size - 1) && (c != '\n'))
{
n = recv(sock, &c, 1, 0);
if (n > 0)
{
if (c == '\r')
{
n = recv(sock, &c, 1, MSG_PEEK);
if ((n > 0) && (c == '\n'))
recv(sock, &c, 1, 0);
else
c = '\n';
}
buf[i] = c;
i++;
}
else
c = '\n';
}
buf[i] = '\0';
return(i);
}
void strdecode(char *to, char *from)
{
for ( ; *from != '\0'; ++to, ++from) {
if (from[0] == '%' && isxdigit(from[1]) && isxdigit(from[2])) {
*to = hexit(from[1])*16 + hexit(from[2]);
from += 2;
} else
*to = *from;
}
*to = '\0';
}
int hexit(char c)
{
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
return 0;
}
void strencode(char* to, size_t tosize, const char* from)
{
int tolen;
for (tolen = 0; *from != '\0' && tolen + 4 < tosize; ++from) {
if (isalnum(*from) || strchr("/_.-~", *from) != (char*)0) {
*to = *from;
++to;
++tolen;
} else {
sprintf(to, "%%%02x", (int) *from & 0xff);
to += 3;
tolen += 3;
}
}
*to = '\0';
}
#include <unistd.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#include <signal.h>
#include <dirent.h>
#include "pub.h"
#include "wrap.h"
int http_request(int cfd, int epfd);
int main()
{
struct sigaction act;
act.sa_handler = SIG_IGN;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGPIPE, &act, NULL);
char path[255] = {0};
sprintf(path, "%s/%s", getenv("HOME"), "webpath");
chdir(path);
printf("path==[%s]\n", path);
int lfd = tcp4bind(9999, NULL);
Listen(lfd, 128);
int epfd = epoll_create(1024);
if(epfd<0)
{
perror("epoll_create error");
close(lfd);
return -1;
}
struct epoll_event ev;
ev.data.fd = lfd;
ev.events = EPOLLIN;
epoll_ctl(epfd, EPOLL_CTL_ADD, lfd, &ev);
int i;
int cfd;
int nready;
int sockfd;
struct epoll_event events[1024];
while(1)
{
nready = epoll_wait(epfd, events, 1024, -1);
if(nready<0)
{
if(errno==EINTR)
{
continue;
}
break;
}
for(i=0; i<nready; i++)
{
sockfd = events[i].data.fd;
if(sockfd==lfd)
{
cfd = Accept(lfd, NULL, NULL);
int flag = fcntl(cfd, F_GETFL);
flag |= O_NONBLOCK;
fcntl(cfd, F_SETFL, flag);
ev.data.fd = cfd;
ev.events = EPOLLIN;
epoll_ctl(epfd, EPOLL_CTL_ADD, cfd, &ev);
}
else
{
http_request(sockfd, epfd);
}
}
}
}
int send_header(int cfd, char *code, char *msg, char *fileType, int len)
{
char buf[1024] = {0};
sprintf(buf, "HTTP/1.1 %s %s\r\n", code, msg);
sprintf(buf+strlen(buf), "Content-Type:%s\r\n", fileType);
if(len>0)
{
sprintf(buf+strlen(buf), "Content-Length:%d\r\n", len);
}
strcat(buf, "\r\n");
Write(cfd, buf, strlen(buf));
return 0;
}
int send_file(int cfd, char *fileName)
{
int fd = open(fileName, O_RDONLY);
if(fd<0)
{
perror("open error");
return -1;
}
int n;
char buf[1024];
while(1)
{
memset(buf, 0x00, sizeof(buf));
n = read(fd, buf, sizeof(buf));
if(n<=0)
{
break;
}
else
{
Write(cfd, buf, n);
}
}
}
int http_request(int cfd, int epfd)
{
int n;
char buf[1024];
memset(buf, 0x00, sizeof(buf));
n = Readline(cfd, buf, sizeof(buf));
if(n<=0)
{
close(cfd);
epoll_ctl(epfd, EPOLL_CTL_DEL, cfd, NULL);
return -1;
}
printf("buf==[%s]\n", buf);
char reqType[16] = {0};
char fileName[255] = {0};
char protocal[16] = {0};
sscanf(buf, "%[^ ] %[^ ] %[^ \r\n]", reqType, fileName, protocal);
printf("--[%s]--\n", fileName);
char *pFile = fileName;
if(strlen(fileName)<=1)
{
strcpy(pFile, "./");
}
else
{
pFile = fileName+1;
}
strdecode(pFile, pFile);
printf("[%s]\n", pFile);
while((n=Readline(cfd, buf, sizeof(buf)))>0);
struct stat st;
if(stat(pFile, &st)<0)
{
printf("file not exist\n");
send_header(cfd, "404", "NOT FOUND", get_mime_type(".html"), 0);
send_file(cfd, "error.html");
}
else
{
if(S_ISREG(st.st_mode))
{
printf("file exist\n");
send_header(cfd, "200", "OK", get_mime_type(pFile), st.st_size);
send_file(cfd, pFile);
}
else if(S_ISDIR(st.st_mode))
{
printf("目录文件\n");
char buffer[1024];
send_header(cfd, "200", "OK", get_mime_type(".html"), 0);
send_file(cfd, "html/dir_header.html");
struct dirent **namelist;
int num;
num = scandir(pFile, &namelist, NULL, alphasort);
if (num < 0)
{
perror("scandir");
close(cfd);
epoll_ctl(epfd, EPOLL_CTL_DEL, cfd, NULL);
return -1;
}
else
{
while (num--)
{
printf("%s\n", namelist[num]->d_name);
memset(buffer, 0x00, sizeof(buffer));
if(namelist[num]->d_type==DT_DIR)
{
sprintf(buffer, "<li><a href=%s/>%s</a></li>", namelist[num]->d_name, namelist[num]->d_name);
}
else
{
sprintf(buffer, "<li><a href=%s>%s</a></li>", namelist[num]->d_name, namelist[num]->d_name);
}
free(namelist[num]);
Write(cfd, buffer, strlen(buffer));
}
free(namelist);
}
sleep(10);
send_file(cfd, "html/dir_tail.html");
}
}
return 0;
}