Linux网络编程-多进程、多线程服务器
源码
多进程服务器
server.c
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <errno.h>
#define SERV_PORT 8080
#define LISTENQ 10
void sid_child (int signo) {
pid_t pid;
int stat;
while ((pid = waitpid (-1, &stat, WNOHANG)) > 0);
return;
}
int main (int argc, char **argv) {
int listenFd, connFd, ret;
pid_t childPid;
socklen_t cliLen;
struct sockaddr_in clientAddr, serverAddr;
listenFd = socket (AF_INET, SOCK_STREAM, 0);
if (listenFd < 0) {
printf ("[server] socket error: %s\n", strerror (errno));
exit (-1);
}
bzero (&serverAddr, sizeof (serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = htonl (INADDR_ANY);
serverAddr.sin_port = htons (SERV_PORT);
ret = bind (listenFd, (struct sockaddr*) &serverAddr, sizeof (serverAddr));
if (ret < 0) {
printf ("[server] bind error: %s\n", strerror (errno));
exit (-1);
}
ret = listen (listenFd, LISTENQ);
if (ret < 0) {
printf ("[server] listen error: %s\n", strerror (errno));
exit (-1);
}
signal (SIGCHLD, sid_child);
while (1) {
cliLen = sizeof (clientAddr);
connFd = accept (listenFd, (struct sockaddr*) &clientAddr, &cliLen);
if ((childPid = fork()) == 0) {
close (listenFd);
time_t now;
time (&now);
char buf[20] = {0};
sprintf (buf, "%s", asctime (gmtime (&now)));
write (connFd, buf, 20);
close (connFd);
exit (0);
}
close (connFd);
}
}
多线程服务器
server.c
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include "threadPool.h"
#define SERV_PORT 8080
#define BUF_SIZE 1024
#define LISTENQ 10
int* u_intcpy (int n) {
int *ret = (int*) malloc (sizeof (int));
*ret = n;
return ret;
}
char* join (char *a, char *catb, char *c) {
char *ret;
int i = strlen (a), j = strlen (catb), k = strlen (c), n;
ret = (char*) malloc (sizeof (char) * (i + j + k + 1));
for (n = 0; n < i; n++)
ret[n] = a[n];
for (n = 0; n < j; n++)
ret[i + n] = catb[n];
i += j;
for (n = 0; n < k; n++)
ret[i + n] = c[n];
ret[i + n] = 0;
return ret;
}
void timeService (int sockFd) {
time_t now;
time (&now);
char buf[20] = {0};
sprintf (buf, "%s", asctime (gmtime (&now)));
write (sockFd, buf, 20);
}
void* handle (void *arg) {
int sockFd = *(int*) arg;
char c;
while (1) {
read (sockFd, &c, 1);
if (c == '1')
timeService (sockFd);
else if (c == '2')
break;
}
free (arg);
close (sockFd);
}
int main (int argc, char **argv) {
int listenFd, connFd, ret;
struct sockaddr_in clientAddr, serverAddr;
socklen_t cliLen;
ThreadPool *pool = createThreadPool (10);
listenFd = socket (AF_INET, SOCK_STREAM, 0);
if (listenFd < 0) {
printf("[server] socket error: %s\n", strerror(errno));
exit(-1);
}
bzero (&serverAddr, sizeof (serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = htonl (INADDR_ANY);
serverAddr.sin_port = htons (SERV_PORT);
ret = bind (listenFd, (struct sockaddr*) &serverAddr, sizeof (serverAddr));
if (ret != 0) {
close(listenFd);
printf("[server] bind error: %s\n", strerror(errno));
exit(-1);
}
ret = listen (listenFd, LISTENQ);
if (ret != 0) {
close(listenFd);
printf("[server] listen error: %s\n", strerror(errno));
exit(-1);
}
while (1) {
cliLen = sizeof (clientAddr);
connFd = accept (listenFd, (struct sockaddr*) &clientAddr, &cliLen);
submitTask (pool, handle, u_intcpy (connFd));
}
close (listenFd);
destoryThreadPool (pool);
}
threadPool.h
#ifndef _ThreadPool
#define _ThreadPool
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
typedef struct executor {
void *(*task) (void *arg);
void *arg;
struct executor *next;
} ThreadExecutor;
typedef struct {
pthread_mutex_t queueLock;
pthread_cond_t queueReady;
ThreadExecutor *queueHead; // all tasks waiting to be executed
int shutdown;
pthread_t *threadId;
int maxThreadNum; // number of active thread in pool
int curQueueSize; // number of task wait in queue
} ThreadPool;
ThreadPool* createThreadPool (int maxThreadNum);
void submitTask (ThreadPool *pool, void *(*task) (void *arg), void *arg);
int destroyThreadPool (ThreadPool *pool);
#endif
threadPool.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <assert.h>
#include <string.h>
#include "threadPool.h"
#define TRUE 1
#define FALSE 0
void *threadRoutine (void *arg) {
ThreadPool *pool = (ThreadPool*) arg;
while (TRUE) {
pthread_mutex_lock (&(pool->queueLock)); // lock
// waiting for task
while (pool->curQueueSize == 0 && !pool->shutdown)
pthread_cond_wait (&(pool->queueReady), &(pool->queueLock));
// exit thread if pool->shutdown is true
if (pool->shutdown) {
pthread_mutex_unlock (&(pool->queueLock));
pthread_exit (NULL);
}
assert (pool->curQueueSize != 0);
assert (pool->queueHead != NULL);
// get the head in queue
pool->curQueueSize--;
ThreadExecutor *executor = pool->queueHead;
pool->queueHead = executor->next;
pthread_mutex_unlock (&(pool->queueLock));
// execute
(*(executor->task)) (executor->arg);
free (executor);
executor = NULL;
}
pthread_exit (NULL); // this line should be unreachable
}
ThreadPool* createThreadPool (int maxThreadNum) {
ThreadPool *pool = (ThreadPool*) malloc (sizeof (ThreadPool));
bzero (pool, sizeof (ThreadPool));
pthread_mutex_init (&(pool->queueLock), NULL);
pthread_cond_init (&(pool->queueReady), NULL);
pool->maxThreadNum = maxThreadNum;
pool->threadId = (pthread_t*) malloc (maxThreadNum * sizeof (pthread_t));
int i;
for (i = 0; i < maxThreadNum; i++)
pthread_create (&(pool->threadId[i]), NULL, threadRoutine, pool);
return pool;
}
void submitTask (ThreadPool *pool, void *(*task) (void *arg), void *arg) {
ThreadExecutor *newExecutor = (ThreadExecutor*) malloc (sizeof (ThreadExecutor));
newExecutor->task = task;
newExecutor->arg = arg;
newExecutor->next = NULL;
pthread_mutex_lock (&(pool->queueLock)); // lock
ThreadExecutor *executor = pool->queueHead;
if (executor != NULL) {
while (executor->next != NULL)
executor = executor->next;
executor->next = newExecutor;
}
else pool->queueHead = newExecutor;
pool->curQueueSize++;
pthread_mutex_unlock (&(pool->queueLock)); // unlock
pthread_cond_signal (&(pool->queueReady)); // notify thread blocked
}
int destroyThreadPool (ThreadPool *pool) {
if (pool != NULL) {
if (pool->shutdown)
return -1;
pool->shutdown = TRUE;
pthread_cond_broadcast (&(pool->queueReady)); // notify all sleeping thread
// blocking to wait for threads
int i;
for (i = 0; i < pool->maxThreadNum; i++)
pthread_join (pool->threadId[i], NULL);
free(pool->threadId);
// destroy executor queue
ThreadExecutor *head = NULL;
while (pool->queueHead != NULL) {
head = pool->queueHead;
pool->queueHead = pool->queueHead->next;
free(head);
}
pthread_mutex_destroy (&(pool->queueLock));
pthread_cond_destroy (&(pool->queueReady));
free(pool);
return 0;
}
return -1;
}
客户端
client.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <errno.h>
#define SERV_IP "127.0.0.1"
#define SERV_PORT 8080
#define BUF_SIZE 512
int main (int argc, char **argv) {
int sockFd, ret;
struct sockaddr_in serverAddr;
sockFd = socket (AF_INET, SOCK_STREAM, 0);
bzero(&serverAddr, sizeof (serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons (SERV_PORT);
inet_pton (AF_INET, SERV_IP, &serverAddr.sin_addr);
ret = connect (sockFd, (struct sockaddr*) &serverAddr, sizeof (serverAddr));
if (ret < 0) {
printf ("connect error: %s\n", strerror (errno));
exit (-1);
}
char buf[BUF_SIZE] = {0};
if (read (sockFd, buf, BUF_SIZE) == 0) {
printf ("str_cli: server terminated prematurely");
exit (-1);
}
printf ("[server] %s\n", buf);
close (sockFd);
exit(0);
}
多进程版客户端(模拟多客户端并发)
client.c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <signal.h>
#define SERV_IP "127.0.0.1"
#define SERV_PORT 8080
#define BUFFER_SIZE 1024
int childRunning = 1;
void sid_child (int signo) {
pid_t pid;
int stat;
while ((pid = waitpid (-1, &stat, WNOHANG)) > 0);
childRunning = 0;
}
void client () {
int sockFd, ret;
struct sockaddr_in serverAddr;
sockFd = socket (AF_INET, SOCK_STREAM, 0);
if (sockFd < 0) {
printf("socket error: %s\n", strerror(errno));
exit(-1);
}
bzero (&serverAddr, sizeof (serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons (SERV_PORT);
inet_pton (AF_INET, SERV_IP, &serverAddr.sin_addr);
ret = connect (sockFd, (struct sockaddr*) &serverAddr, sizeof (serverAddr));
if (ret != 0) {
close(sockFd);
printf("connect error: %s\n", strerror(errno));
exit(-1);
}
char buf[BUFFER_SIZE] = {0};
write (sockFd, "1", 1);
if (read (sockFd, buf, BUFFER_SIZE) > 0)
printf ("[server] %s\n", buf);
bzero (buf, BUFFER_SIZE);
write (sockFd, "2", 1);
close (sockFd);
}
int main (int argc, char **argv) {
if (argc == 2) {
int clientNum, clientPid;
sscanf (argv[1], "%d", &clientNum);
signal (SIGCHLD, sid_child);
for (; clientNum > 0; clientNum--) {
if ((clientPid = fork()) == 0) {
client ();
exit (0);
}
}
while (childRunning);
}
exit (0);
}