1.基于进程的并发编程
#include "csapp.h"
void echo(int connfd);
void sigchld_handler(int sig)
{
while (waitpid(-1, 0, WNOHANG) > 0)
;
return;
}
int main(int argc, char **argv)
{
int listenfd, connfd, port, clientlen = sizeof(struct sockaddr_in);
struct sockaddr_in clientaddr;
struct hostent *hp;
char *haddrp;
if (argc != 2)
{
fprintf(stderr, "usage: %s <port>\n", argv[0]);
exit(0);
}
port = atoi(argv[1]);
Signal(SIGCHLD, sigchld_handler);
listenfd = Open_listenfd(port);
while (1)
{
connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen);
if (Fork() == 0)
{
Close(listenfd);
hp = Gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr,
sizeof(clientaddr.sin_addr.s_addr), AF_INET);
haddrp = inet_ntoa(clientaddr.sin_addr);
printf("server connected to %s (%s)\n", hp->h_name, haddrp);
echo(connfd);
Close(connfd);
exit(0);
}
Close(connfd);
}
exit(0);
}
2.基于I/O多路复用,实现了多个客户端的echo服务器
#include "csapp.h"
typedef struct
{
int maxfd;
fd_set read_set;
fd_set ready_set;
int nready;
int maxi;
int clientfd[FD_SETSIZE];
rio_t clientrio[FD_SETSIZE];
}pool;
void init_pool(int listenfd, pool* p);
void add_client(int connfd, pool* p);
void check_clients(pool* p);
int byte_cnt=0;
int main(int argc, char **argv)
{
int listenfd, connfd, port, clientlen = sizeof(struct sockaddr_in);
struct sockaddr_in clientaddr;
struct hostent *hp;
static pool pool;
char *haddrp;
fd_set read_set,ready_set;
if (argc != 2)
{
fprintf(stderr, "usage: %s <port>\n", argv[0]);
exit(0);
}
port = atoi(argv[1]);
listenfd = Open_listenfd(port);
init_pool(listenfd, &pool);
while (1)
{
pool.ready_set = pool.read_set;
pool.nready = Select(pool.maxfd+1, &pool.ready_set, NULL, NULL, NULL);
if(FD_ISSET(listenfd, &pool.ready_set))
{
connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen);
hp = Gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr,
sizeof(clientaddr.sin_addr.s_addr), AF_INET);
haddrp = inet_ntoa(clientaddr.sin_addr);
printf("server connected to %s (%s)\n", hp->h_name, haddrp);
add_client(connfd, &pool);
}
check_clients(&pool);
}
exit(0);
}
void init_pool(int listenfd, pool* p)
{
int i;
p->maxi = -1;
for(i=0; i<FD_SETSIZE; i++)
p->clientfd[i] = -1;
p->maxfd = listenfd;
FD_ZERO(&p->read_set);
FD_SET(listenfd, &p->read_set);
}
void add_client(int connfd, pool* p)
{
int i;
p->nready--;
for (i = 0; i < FD_SETSIZE; i++)
if (p->clientfd[i] < 0)
{
p->clientfd[i] = connfd;
Rio_readinitb(&p->clientrio[i], connfd);
FD_SET(connfd, &p->read_set);
if (connfd > p->maxfd)
p->maxfd = connfd;
if (i > p->maxi)
p->maxi = i;
break;
}
if(i == FD_SETSIZE)
app_error("add_client error: Too many clients");
}
void check_clients(pool* p)
{
int i, connfd, n;
char buf[MAXLINE];
rio_t rio;
for (i = 0; (i <= p->maxi) && (p->nready > 0); i++)
{
connfd = p->clientfd[i];
rio = p->clientrio[i];
if ((n = Rio_readlineb(&rio, buf, MAXLINE)) != 0)
{
byte_cnt +=n;
printf("Server received %d (%d total) bytes on fd %d\n",
n, byte_cnt, connfd);
Rio_writen(connfd, buf, n);
}
else
{
Close(connfd);
FD_CLR(connfd, &p->read_set);
p->clientfd[i] = -1;
}
}
}
3.基于多线程,实现了多个客户端的echo服务器
#include "csapp.h"
void Pthread_create(pthread_t *tidp, pthread_attr_t *attrp,
void * (*routine)(void *), void *argp)
{
int rc;
if ((rc = pthread_create(tidp, attrp, routine, argp)) != 0)
posix_error(rc, "Pthread_create error");
}
void Pthread_cancel(pthread_t tid)
{
int rc;
if ((rc = pthread_cancel(tid)) != 0)
posix_error(rc, "Pthread_cancel error");
}
void Pthread_join(pthread_t tid, void **thread_return)
{
int rc;
if ((rc = pthread_join(tid, thread_return)) != 0)
posix_error(rc, "Pthread_join error");
}
void Pthread_detach(pthread_t tid)
{
int rc;
if ((rc = pthread_detach(tid)) != 0)
posix_error(rc, "Pthread_detach error");
}
void Pthread_exit(void *retval)
{
pthread_exit(retval);
}
pthread_t Pthread_self(void)
{
return pthread_self();
}
void Pthread_once(pthread_once_t *once_control, void (*init_function)()) {
pthread_once(once_control, init_function);
}
void echo(int connfd);
void* thread(void* vargp);
int main(int argc, char **argv)
{
int listenfd, *connfdp, port, clientlen = sizeof(struct sockaddr_in);
struct sockaddr_in clientaddr;
pthread_t tid;
if (argc != 2)
{
fprintf(stderr, "usage: %s <port>\n", argv[0]);
exit(0);
}
port = atoi(argv[1]);
listenfd = Open_listenfd(port);
while (1)
{
connfdp = (int*)Malloc(sizeof(int));
*connfdp =Accept(listenfd, (SA *)&clientaddr, &clientlen);
Pthread_create(&tid, NULL, thread, connfdp);
}
exit(0);
}
void* thread(void* vargp)
{
int connfd = *((int*)vargp);
printf("server connected to a client.\n");
Free(vargp);
echo(connfd);
Close(connfd);
return NULL;
}