linux 多线程 代码,Linux 多线程服务器源代码详解

对http://tuoxie174.blog.51cto.com/1446064/413189 的源代码分析

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

using namespace std;

#define PORT        8848  //Port

#define BACKLOG     5     // Max Link num

#define MAXDATASIZE 1000  // Max data buf

#define DEBUG 1

//1. Func Decalare

void process_cli(int connectfd, sockaddr_in client);

int  sendobj(int connectfd, char* serverfilepath);

int  isDIR(char* path);

int  fileordirExist(char* fpath);

char* gettextname(char*);

int   writehead(FILE* cfp, char* extname);

void* start_routing(void* arg);

void  msg404(int connectfd);

//2. Structure Decalare

struct ARG

{

int         connfd;

sockaddr_in client;

};

int main()

{

//cout << "Hello world!" << endl;

int listenfd, connectfd;

//! 1. thread id

pthread_t thread;

//! 2. pass this var to the thread

ARG*      arg;

struct sockaddr_in server;

struct sockaddr_in client;

int    sin_size;

//! 3. create tcp socket

#ifdef DEBUG

printf("socket...\n");

#endif

if((listenfd=socket(AF_INET,SOCK_STREAM,0))==-1)

{

perror("creating socket failed!\n");

exit(1);

}

//! 4. set the socket -- close, timeout

int opt = SO_REUSEADDR;

setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

bzero(&server, sizeof(server));

server.sin_family = AF_INET;

server.sin_port   = htons(PORT);

server.sin_addr.s_addr = htonl(INADDR_ANY);

printf("bind...\n");

//! 5. bind a ip and port to the socket

if(bind(listenfd, (struct sockaddr*)&server, sizeof(struct sockaddr)))

{

perror("bind error!");

exit(1);

}

printf("listen...\n");

//! 6. listen the socket

if(listen(listenfd,BACKLOG)==-1)

{

perror("listen error!\n");

exit(1);

}

// a datastructure for programmer to use struct sockaddr

sin_size = sizeof(struct sockaddr_in);

while(1)

{

// begin to process the client's connect

//! 7. accept using main thread

printf("accepting...\n");

if((connectfd=accept(listenfd, (struct sockaddr*)&client, (socklen_t*)&sin_size))==-1)

{

printf("accept error!\n");

}

//connectfd is a socket

arg = new ARG;

arg->connfd = connectfd;

memcpy((void*)&arg->client, &client, sizeof(client));

#ifdef DEBUG

printf("thread creating...\n");

#endif

//! 8. invoke start_routing to handle this thread. -- start_routing is a callback func

if(pthread_create(&thread, NULL, start_routing, (void*)arg))

{

perror("pthread_create error!\n");

exit(1);

}

}

close(listenfd);

return 0;

}

//! 1.1 handle the request

void process_cli(int connectfd, sockaddr_in client)

{

int  num;

char requestline[MAXDATASIZE];

char filepath[MAXDATASIZE];

char cmd[MAXDATASIZE];

char extname[MAXDATASIZE];

int c;

FILE *fp;

//! Because everything is file in UNIX

//! 1.1.1 open the client socket

fp = fdopen(connectfd, "r");

#ifdef DEBUG

printf("the host is: %s \n", inet_ntoa(client.sin_addr));

#endif

fgets(requestline, MAXDATASIZE, fp);

#ifdef DEBUG

printf("The request is: %s \n", requestline);

#endif

strcpy(filepath, "./");

sscanf(requestline, "%s%s\n", cmd, filepath+2);

//! use func gettextname

strcpy(extname, gettextname(filepath));

#ifdef DEBUG

printf("cmd: %s\n filepath: %s\n extname: %s\n", cmd, filepath, extname);

printf("string comparing\n:::::::start:::::::\n");

#endif

if(strcmp(cmd, "GET")==0)

{

#ifdef DEBUG

printf("cmd(%s)==GET\n", cmd);

#endif

if(fileordirExist(filepath))

{

if(isDIR(filepath))

{

//! is a DIR

#ifdef DEBUG

printf("%s is a DIR \n", filepath);

#endif

if(fileordirExist(strcat(filepath, "index.html")))

{

//! send

sendobj(connectfd, "index.html");

}

else

{

msg404(connectfd);

}

}

else

{

//! is a file

#ifdef DEBUG

printf("%s is a file \n", filepath);

#endif

//! send

sendobj(connectfd, filepath);

}

}

else

{

#ifdef DEBUG

printf("404\n");

#endif

msg404(connectfd);

}

}

else

{

#ifdef DEBUG

printf("cmd(%s)!=GET\n", cmd);

#endif

}

#ifdef DEBUG

printf("::::::::::::::::::::end::::::::::::::::::\n");

close(connectfd);

#endif

}

//! 1.2

void msg404(int connectfd)

{

char* msg;

msg = "HTTP/1.0 404 Not Found Content-Type: text/plain 404 not found by Manio\n";

send(connectfd, msg, strlen(msg), 0);

}

//! 1.3 is the filepath a file or direatory

int fileordirExist(char* fpath)

{

struct stat filestat;

return ( stat(fpath, &filestat)!=-1);

}

//! 1.4 is the filepath a directory

int isDIR(char* fpath)

{

#ifdef DEBUG

printf("IN IsDir\ns");

#endif

struct stat filestat;

return ( stat(fpath, &filestat)!=-1 && S_ISDIR(filestat.st_mode));

}

//! 1.5 send the data of the file which the client want

int sendobj(int connectfd, char* serverfilepath)

{

//printf("server: %s\n", serverfilepath)

FILE* sfp=NULL, *cfp=NULL;

char c;

sfp = fopen(serverfilepath, "r");

cfp = fdopen(connectfd, "w");

if(sfp == NULL)

printf("can't open the file!... \n");

if(cfp == NULL)

printf("can't open the link file...!\n");

writehead(cfp, gettextname(serverfilepath));

while( (c=getc(sfp)) !=EOF){

putc(c, cfp);

//putchar(c);

}

fflush(cfp);

return 0;

}

//! 1.6 write the packet header to the client

int writehead(FILE* cfp, char* extname)

{

#ifdef DEBUG

printf("INWRITEHEAD:::::extname is %s::::::\n", extname);

#endif

char* content = "text/plain";

if(strcmp(extname, "html")==0 || strcmp(extname, "htm")==0)

content = "text/html";

else if(strcmp(extname,"css")==0)

content = "text/css";

else if(strcmp(extname,"gif")==0)

content = "p_w_picpath/gif";

else if(strcmp(extname,"jpeg")==0||strcmp(extname,"jpg")==0)

content = "p_w_picpath/jpeg";

else if(strcmp(extname, "png")==0)

content = "p_w_picpath/png";

#ifdef DEBUG

printf("HTTP/1.1 200 OK\n");

printf("Content-Type: %s \n", content);

#endif

fprintf(cfp, "HTTP/1.1 200 OK ");

fprintf(cfp, "Content-Type: %s \n", content);

return 0;

}

//! 1.7 get the extent name of the file

char* gettextname(char* filepath)

{

char* p;

if((p=strrchr(filepath,'.'))!=NULL)

return p+1;

return NULL;

}

//! 1.8 invoked by pthread_create

void* start_routing(void* arg)

{

ARG* info;

info = (ARG*) arg;

// handle client's requirement

process_cli(info->connfd, info->client);

delete arg;

pthread_exit(NULL);

}

//1.  只要 g++ -g -o execname filename -lpthread

//2. 然后在浏览器输入: 127.0.0.1:8848

//3. 与程序同目录下 有 index.html (注意扩展名, 程序中为判断)

问题: 中文会出现乱码, 查看源代码, 发现

的很大一部分没有了, 只留下后面的, 于是乎编码没有设置。 (英文网页时,前半部分也没了)。 继续解决。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值