文章目录
TCP循环服务器模型 |
TCP多进程并发服务器 |
TCP多线程服务器 |
socket(...);
bind(...);
listen(...);
while(1){
accept(...);
process(...);
close(...);
}
socket(...);
bind(...);
listen(...);
while(1){
accpet(...);
if(fork(...) == 0){
process(...);
close(...);
exit(...);
}
close(...);
}
socket(...);
bind(...);
listen(...);
while(1){
accpet(...);
if((pthread_create(...))!==-1) {
process(...);
close(...);
exit(...);
}
close(...)
}
TCP服务器一般很少用
TCP并发服务器的思想是每一个客户机的请求并不由服务器直接处理,而是由服务器创建一个子进程来处理。
多线程服务器是对多进程的服务器的改进
1,TCP多线程并发服务器
1.1,头文件net.h
#ifndef __NET_H__
#define __NET_H__
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SERV_IP_ADDR "192.168.31.100"
#define SERV_PORT 5005
#define BACKLOG 5
#define QUIT_STR "quite"
#endif
1.2,客户端client.c
>##
#include "net.h"
void usage(char *s)
{
printf("Usage: %s
",s);
printf(" serv_ip: server ip address
");
printf(" serv_port: server port(>5000)
");
}
int main(int argc, const char *argv[])
{
int fd;
short port;
struct sockaddr_in sin;
if(argc != 3)
{
usage((char *)argv[0]);
exit(1);
}
if((port = atoi(argv[2])) < 5000)
{
usage((char *)argv[0]);
exit(1);
}
if((fd = socket(AF_INET,SOCK_STREAM,0)) < 0)
{
perror("socket");
exit(-1);
}
bzero(&sin,sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
if(inet_pton(AF_INET,argv[1],(void *)&sin.sin_addr.s_addr) < 0)
{
perror("inet_pton");
goto _error1;
}
if(connect(fd,(struct sockaddr *)&sin,sizeof(sin)) < 0)
{
perror("connect");
goto _error1;
}
char buf[BUFSIZ];
while(1)
{
bzero(buf,BUFSIZ);
if(fgets(buf,BUFSIZ-1,stdin) == NULL)
{
continue;
}
write(fd,buf,strlen(buf));
if(strncasecmp(buf,QUIT_STR,strlen(QUIT_STR)) == 0)
{
printf("client is existing!
");
break;
}
}
_error1:
close(fd);
return 0;
}
1.3,服务器端server.c
#include "net.h"
#include
typedef struct{
int addr;
int port;
int fd;
}ARG;
void client_data_handle(void *arg);
int main(int argc, const char *argv[])
{
pthread_t tid;
int fd;
struct sockaddr_in sin;
if((fd = socket(AF_INET,SOCK_STREAM,0)) < 0)
{
perror("socket");
exit(-1);
}
int b_reuse = 1;
setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&b_reuse,sizeof(int));
bzero(&sin,sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(SERV_PORT);
#if 1
sin.sin_addr.s_addr = htonl(INADDR_ANY);
#else
if(inet_pton(AF_INET,SERV_IP_ADDR,(void *)&sin.sin_addr.s_addr) < 0)
{
perror("inet_pton");
goto _error1;
}
#endif
if(bind(fd,(struct sockaddr *)&sin,sizeof(sin)))
{
perror("bind");
goto _error1;
}
if(listen(fd,BACKLOG) < 0)
{
perror("listen");
goto _error1;
}
int newfd = -1;
struct sockaddr_in cin;
socklen_t cin_addr_len = sizeof(cin);
while(1)
{
if((newfd = accept(fd,(struct sockaddr *)&cin,&cin_addr_len)) < 0)
{
perror("connect");
goto _error1;
}
ARG arg;
arg.addr = cin.sin_addr.s_addr;
arg.port = ntohs(cin.sin_port);
arg.fd = newfd;
if(pthread_create(&tid,NULL,(void *)client_data_handle,(void *)&arg) != 0)
{
perror("pthread_create");
goto _errno2;
}
}
_errno2:
close(newfd);
_error1:
close(fd);
return 0;
}
void client_data_handle(void *arg)
{
int ret = -1;
char buf[BUFSIZ];
char cin_ipv4_addr[16];
ARG parg = *(ARG *)arg;
if(inet_ntop(AF_INET,&parg.addr,cin_ipv4_addr,sizeof(cin_ipv4_addr)) < 0)
{
perror("inet_ntop");
exit(-1);
}
printf("client(:%s potr(:%d
",cin_ipv4_addr,parg.port);
printf("the client pthread fd is %d
",parg.fd);
while(1)
{
bzero(buf,BUFSIZ);
do
{
ret = read(parg.fd,buf,BUFSIZ-1);
}while(ret < 0 && errno == EINTR);
if(ret < 0)
{
perror("read");
break;
}
if(ret == 0)
{
break;
}
printf("receive data: %s",buf);
if(strncasecmp(buf,QUIT_STR,strlen(QUIT_STR)) == 0)
{
printf("client is existing!
");
break;
}
}
close(parg.fd);
printf("pthread fd %d is closed!
",parg.fd);
}
2,TCP多进程并发服务器
2.1,头文件net.h
#ifndef __NET_H__
#define __NET_H__
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SERV_IP_ADDR "192.168.31.100"
#define SERV_PORT 5005
#define BACKLOG 5
#define QUIT_STR "quite"
#endif
2.2,客户端程序client.c
#include "net.h"
void usage(char *s)
{
printf("Usage: %s
",s);
printf(" serv_ip: server ip address
");
printf(" serv_port: server port(>5000)
");
}
int main(int argc, const char *argv[])
{
int fd;
short port;
struct sockaddr_in sin;
if(argc != 3)
{
usage((char *)argv[0]);
exit(1);
}
if((port = atoi(argv[2])) < 5000)
{
usage((char *)argv[0]);
exit(1);
}
if((fd = socket(AF_INET,SOCK_STREAM,0)) < 0)
{
perror("socket");
exit(-1);
}
bzero(&sin,sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
if(inet_pton(AF_INET,argv[1],(void *)&sin.sin_addr.s_addr) < 0)
{
perror("inet_pton");
goto _error1;
}
if(connect(fd,(struct sockaddr *)&sin,sizeof(sin)) < 0)
{
perror("connect");
goto _error1;
}
char buf[BUFSIZ];
while(1)
{
bzero(buf,BUFSIZ);
if(fgets(buf,BUFSIZ-1,stdin) == NULL)
{
continue;
}
write(fd,buf,strlen(buf));
if(strncasecmp(buf,QUIT_STR,strlen(QUIT_STR)) == 0)
{
printf("client is existing!
");
break;
}
}
_error1:
close(fd);
return 0;
}
2.3,服务器端程序service.c
#include "net.h"
#include
#include
typedef struct{
int addr;
int port;
int fd;
}ARG;
void client_data_handle(ARG *arg);
void sig_child_handle(int signo)
{
if(SIGCHLD == signo)
{
waitpid(-1,NULL,WNOHANG);
}
}
int main(int argc, const char *argv[])
{
int fd;
struct sockaddr_in sin;
pid_t pid;
signal(SIGCHLD,sig_child_handle);
if((fd = socket(AF_INET,SOCK_STREAM,0)) < 0)
{
perror("socket");
exit(-1);
}
int b_reuse = 1;
setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&b_reuse,sizeof(int));
bzero(&sin,sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(SERV_PORT);
#if 1
sin.sin_addr.s_addr = htonl(INADDR_ANY);
#else
if(inet_pton(AF_INET,SERV_IP_ADDR,(void *)&sin.sin_addr.s_addr) < 0)
{
perror("inet_pton");
goto _error1;
}
#endif
if(bind(fd,(struct sockaddr *)&sin,sizeof(sin)))
{
perror("bind");
goto _error1;
}
if(listen(fd,BACKLOG) < 0)
{
perror("listen");
goto _error1;
}
struct sockaddr_in cin;
socklen_t cin_addr_len = sizeof(cin);
while(1)
{
int newfd = -1;
if((newfd = accept(fd,(struct sockaddr *)&cin,&cin_addr_len)) < 0)
{
perror("connect");
goto _error1;
}
if((pid = fork()) < 0)
{
perror("fork");
break;