此種方式是由主線程預先建立多個工作執行緒,並且主線程不斷的監聽連線請求,當有連線請求時先獲得鎖,並將連線放入到連線陣列中,並通知空閒的工作執行緒(即阻塞在條件等待處的工作執行緒)進行請求處理,工作執行緒得到通知後先在連線陣列中拿乙個可用的連線,並將其標記為已處理,然後釋放鎖,執行請求處理函式。此方式處理的開銷要比前一種的方式大,因為要工作執行緒獲得乙個連線要同時處理鎖及條件變數,而前一種方式只需要維護乙個鎖即可。
例子:回射伺服器,即伺服器端接收客戶端來的資料,並將資料原樣返回給客戶端,**在centos5.0測試通過
伺服器端**:
#include
#include
#include
#include
#include
#include
#include
#include
#define serv_port 2003
#define maxline 1024
#define listenq 4
#define clientnum 5
#define maxncli 20
int listenfd;
pthread_t *child;
pthread_mutex_t mutex;
pthread_cond_t cond;
int clifd[maxncli], iput, iget;
/* 客戶請求處理函式 */
void requestprocessfunc(int connfd)
char buf[maxline];
int n;
for(;;) else{
write(connfd, buf, n);
int makelistenbyport(short port)
int listenfd;
struct sockaddr_in servaddr;
listenfd = socket(af_inet, sock_stream, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = af_inet;
servaddr.sin_addr.s_addr = htonl(inaddr_any);
servaddr.sin_port = htons(port);
bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
listen(listenfd, listenq);
return listenfd;
void * threadmain(void *arg)
int connfd;
pthread_mutex_lock(&mutex);
/* 如果連線陣列中沒有有效的連線,即進入阻塞狀態 */
while(iget == iput)
pthread_cond_wait(&cond, &mutex);
/* 當條件被啟用,工作執行緒從連線資料中拿到乙個有效連線,移動有效連線的下標 */
connfd = clifd[iget++];
if(iget == maxncli)
iget = 0;
pthread_mutex_unlock(&mutex);
/* 呼叫請求處理函式 */
requestprocessfunc(connfd);
close(connfd);
void makethread(int n)
pthread_create(&child[n],null, threadmain, (void *)n);
return;
int main(intargc, char **argv)
int i;
socklen_t tmpaddlen, addlen;
int connfd;
pthread_mutex_init(&mutex, null);
pthread_cond_init(&cond, null);
addlen = sizeof(struct sockaddr_in);
listenfd = makelistenbyport(serv_port);
child = (pthread_t*)malloc(sizeof(pthread_t) * clientnum);
if(child == null) {
printf("memory mallocerror!");
exit(0);
/* 建立工作執行緒 */
for(i = 0; i < clientnum; i++) {
makethread(i);
iget = iput = 0;
for(;;) {
tmpaddlen = addlen;
connfd = accept(listenfd, null,&tmpaddlen);
pthread_mutex_lock(&mutex);
clifd[iput++] = connfd;
if(iput == maxncli)
iput = 0;
/* 通知工作執行緒已經有連線請求 */
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
客戶端**:
#include
#include
#include
#include
#include
#include
#include
#define maxline 1024
#define serv_port 2003
void cli_str(file *fp, int sockfd)
char sendline[maxline];
char recvline[maxline];
memset(recvline, 0x00, sizeof(recvline));
memset(sendline, 0x00, sizeof(sendline));
printf("cli#");
while((fgets(sendline, maxline, fp)) != null) {
write(sockfd, sendline, strlen(sendline));
if(read(sockfd, recvline, maxline) == 0) {
printf("str_cli:server terminated prematurely\n");
exit(0);
fputs(recvline, stdout);
fflush(stdout);
memset(recvline, 0x00, sizeof(recvline));
printf("cli#");
int main(int argc, char **argv)
int sockfd;
struct sockaddr_in servaddr;
if((sockfd = socket(af_inet, sock_stream, 0)) == -1) {
printf("socket error\n");
exit(0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = af_inet;
inet_pton(af_inet, argv[1], &servaddr.sin_addr);
servaddr.sin_port = htons(serv_port);
if((connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)))== -1) {
printf("connect error\n");
exit(0);
cli_str(stdin, sockfd);
exit(0);
Unix網路程式設計伺服器設計方式之二
此方式首先伺服器端建立乙個監聽,並阻塞至accetp處,當乙個客戶端進行連線時,accept函式並啟用並返回,此時用fork函式建立乙個子程序,由子程序執行客戶請求處理程式,而父程序繼續監聽,等待其他的客戶端。此方式會建立很多的程序,程序個數受具體的作業系統的限制。這種併發伺服器的缺點在於建立乙個子...
Unix網路程式設計伺服器設計方式之四
預先建立子程序的方式比為每個客戶端建立乙個程序的方式優越的地方在於當伺服器啟動時就將子程序建立好,當乙個客戶端連線至伺服器時選擇乙個可用的子程序處理,這樣可以節省到建立子程序的消耗。有乙個弊端是需要事先確定子程序的個數,當客戶端多於子程序的個數時,基於的客戶端只能等待可用的子程序。有一種解決方法就是...
UNIX網路程式設計 併發伺服器(多程序)
以下程式的源 均是unix網路程式設計上的例子程式。intro daytimetcpsrv1.c include unp.h include include apueerror.h int main int argc,char argv tcp一般採用併發伺服器。當服務乙個客戶請求可能花費較長時間時...