多线程并发服务器 在使用线程模型开发服务器时需考虑以下问题: 4. 调整进程内最大文件描述符上限 5. 线程如有共享数据,考虑线程同步 6. 服务于客户端线程退出时,退出处理。(退出值,分离态) 7. 系统负载,随着链接客户端增加,导致其它线程不能及时得到CPU
server.cpp
#include <iostream>
#include <strings.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <ctype.h>
#include <fcntl.h>
#include <assert.h>
using namespace std;
#define MAXLINE 1024
#define SERV_PORT 8000
struct s_info{
struct sockaddr_in cliaddr;
int connfd;
};
void *do_work(void *arg){
int n,i;
struct s_info *ts = (struct s_info*)arg;
char buf[MAXLINE];
char str[INET_ADDRSTRLEN];
while(1){
n = read(ts->connfd,buf,MAXLINE);
if(n == 0){
cout << "the client " << ts->connfd << " closed..." << endl;
break;
}
cout << "received from "
<< inet_ntop(AF_INET,&(*ts).cliaddr.sin_addr,str,sizeof(str))
<< " PORT "
<< ntohs((*ts).cliaddr.sin_port)
<< endl;
for(i = 0;i < n;i++){
buf[i] = toupper(buf[i]);
}
write(STDOUT_FILENO,buf,n);
write(ts->connfd,buf,n);
}
close(ts->connfd);
return NULL;
}
int main(){
struct sockaddr_in servaddr,cliaddr;
struct s_info ts[256];
socklen_t cliaddr_len = sizeof(cliaddr);
int listenfd = socket(AF_INET,SOCK_STREAM,0);
assert(listenfd >= 0);
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
int ret = bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr));
assert(ret != -1);
ret = listen(listenfd,128);
assert(ret != -1);
cout << "Accepting client connect ..." << endl;
int i = 0;
while(1){
int connfd = accept(listenfd,(struct sockaddr*)&cliaddr,&cliaddr_len);
ts[i].cliaddr = cliaddr;
ts[i].connfd = connfd;
pthread_t tid;
pthread_create(&tid,NULL,do_work,(void*)&ts[i]);
pthread_detach(tid);
i++;
}
return 0;
}
client.cpp
#include <iostream>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <strings.h>
#include <string.h>
using namespace std;
#define SERV_PORT 8000
#define MAXLINE 4096
int main(){
struct sockaddr_in servaddr;
char buf[MAXLINE];
int sockfd = socket(AF_INET,SOCK_STREAM,0);
assert(sockfd >= 0);
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
inet_pton(AF_INET,"127.0.0.1",&servaddr.sin_addr);
int ret = connect(sockfd,(struct sockaddr*)&servaddr,sizeof(sockaddr));
if(ret < 0){
perror("connect error ");
exit(1);
}
while(fgets(buf,MAXLINE,stdin) != NULL){
write(sockfd,buf,strlen(buf));
int n = read(sockfd,buf,MAXLINE);
if(n == 0){
cout << "the other side has been closed" << endl;
break;
}else{
write(STDOUT_FILENO,buf,n);
}
}
close(sockfd);
return 0;
}
|