多进程并发服务器
设计流程
框架一(使用信号回收僵尸进程)
void handler(int sig)
{
while(waitpid(-1, NULL, WNOHANG) > 0);
}
int main()
{
siganl(17, handler);
server = socket();
bind();
listen();
while(1)
{
client = accept();
if(fork() == 0)
{
close(server);
while(1)
{
recv();
send();
}
close(client);
exit(0);
}
close(client);
}
close(server);
}
实例
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LOG(s) printf("[%s] {%s:%d} %s \n", __DATE__, __FILE__, __LINE__, s);
void cil(int client, struct sockaddr_in caddr);
void handler(int sig)
{
while(waitpid(-1, NULL, WNOHANG) > 0);
}
int main(int argc, char *argv[])
{
signal(17, handler);
int server = -1;
if((server = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
LOG("socket error");
return -1;
}
struct sockaddr_in saddr = {0};
saddr.sin_family = AF_INET;
saddr.sin_port = htons(8888);
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(server, (struct sockaddr*)&saddr, sizeof(saddr)) == -1)
{
LOG("bind error");
return -1;
}
if(listen(server, 5) == -1)
{
LOG("listen error");
return -1;
}
puts("Tcp server start success");
int client = -1;
struct sockaddr_in caddr = {0};
socklen_t len = sizeof(caddr);
pid_t pid = -1;
while(1)
{
if((client = accept(server, (struct sockaddr*)&caddr, &len)) == -1)
{
LOG("accpet error");
return -1;
}
printf("[%s/%d] client已上线\n", inet_ntoa(caddr.sin_addr), ntohl(caddr.sin_port));
if((pid = fork()) < 0)
{
LOG("fork error");
return -1;
}
else if(pid == 0)
{
cil(client, caddr);
exit(0);
}
close(client);
}
close(server);
return 0;
}
void cil(int client, struct sockaddr_in caddr)
{
char buf[128] = "";
int res = 0;
while(1)
{
bzero(buf, sizeof(buf));
if((res = read(client, buf, sizeof(buf))) < 0)
{
LOG("read error");
break;
}
else if(res == 0)
{
printf("[%s/%d] client已下线\n", inet_ntoa(caddr.sin_addr), ntohl(caddr.sin_port));
close(client);
break;
}
printf("[%s/%d] client: %s\n", inet_ntoa(caddr.sin_addr), ntohl(caddr.sin_port), buf);
bzero(buf, sizeof(buf));
strcpy(buf, "ok");
if(write(client, buf, sizeof(buf)) < 0)
{
LOG("write error");
break;
}
}
}
框架二(使用孤儿进程机制避免僵尸进程产生)
int main()
{
server = socket();
bind();
listen();
while(1)
{
if((pid = fork()) == 0)
{
client = accept();
if(pid = fork() == 0)
{
while(1)
{
recv();
send();
}
close(client);
exit(0);
}
else if(pid > 0)
{
close(server);
close(client);
exit(0);
}
}
else if(pid > 0)
{
while(waitpid() == pid)
}
}
close(server);
}
实例
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LOG(s) printf("[%s] {%s:%d} %s\n", __DATE__, __FILE__, __LINE__, s);
void deal_cil_msg(int client, struct sockaddr_in caddr);
int main(int argc, char *argv[])
{
int server = 0;
if((server = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
LOG("socket error");
return -1;
}
struct sockaddr_in saddr = {0};
saddr.sin_family = AF_INET;
saddr.sin_port = htons(8888);
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(server, (struct sockaddr*)&saddr, sizeof(saddr)) == -1)
{
LOG("bind error");
return -1;
}
if(listen(server, 5) == -1)
{
LOG("listen error");
return -1;
}
puts("server start success");
struct sockaddr_in caddr = {0};
int client = 0;
socklen_t asize = sizeof(caddr);
pid_t pid = -1;
int status = 0;
while(1)
{
pid = fork();
if(pid < 0)
{
LOG("fork error");
return -1;
}
if(pid == 0)
{
if((client = accept(server, (struct sockaddr*)&caddr, &asize)) == -1)
{
LOG("accept error");
return -1;
}
printf("[%s/%d]client已上线\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));
pid = fork();
if(pid < 0)
{
LOG("fork error");
return -1;
}
else if(pid == 0)
{
deal_cil_msg(client, caddr);
close(client);
exit(0);
}
else if(pid > 0)
{
close(server);
close(client);
exit(0);
}
}
else if(pid > 0)
{
printf("wait child = %d\n", pid);
while(waitpid(pid, &status, 0) == pid)
{
printf("Parent is over - child: %d, status = %x\n", pid, status);
}
}
}
close(server);
return 0;
}
void deal_cil_msg(int client, struct sockaddr_in caddr)
{
char buf[128] = " ";
while(1)
{
int len = 0;
bzero(buf, sizeof(buf));
if((len = recv(client, buf, sizeof(buf), 0)) < 0)
{
LOG("recv error");
}
else if(len == 0)
{
printf("[%s/%d]client已下线\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));
break;
}
printf("[%s/%d]client: %s\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port), buf);
bzero(buf, sizeof(buf));
strcpy(buf, "ok");
write(client, buf, len);
}
}
多线程并发服务器
设计流程
typedef struct
{
int client;
struct sockaddr_in caddr;
} Client_msg;
int main()
{
server = socket();
bind();
listen();
while(1)
{
client = accpet();
pthread_create();
while(1)
{
}
pthread_detach();
}
close(server);
}
实例
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LOG(s) printf("[%s] {%s:%d} %s \n", __DATE__, __FILE__, __LINE__, s);
void* cil(void* arg);
typedef struct
{
int client;
struct sockaddr_in caddr;
} Cli_msg;
int main(int argc, char *argv[])
{
int server = -1;
if((server = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
LOG("socket error");
return -1;
}
struct sockaddr_in saddr = {0};
saddr.sin_family = AF_INET;
saddr.sin_port = htons(8899);
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(server, (struct sockaddr*)&saddr, sizeof(saddr)) == -1)
{
LOG("bind error");
return -1;
}
if(listen(server, 5) == -1)
{
LOG("listen error");
return -1;
}
puts("tcp server start success");
struct sockaddr_in caddr = {0};
socklen_t len = sizeof(caddr);
pthread_t tid = -1;
int client = -1;
Cli_msg cli_msg;
while(1)
{
if((client = accept(server, (struct sockaddr*)&caddr, &len)) == -1)
{
LOG("accept error");
return -1;
}
printf("[%s/%d]client已上线\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));
cli_msg.client = client;
cli_msg.caddr = caddr;
if(pthread_create(&tid, NULL, cil, &cli_msg) != 0)
{
LOG("pthread_create error");
return -1;
}
pthread_detach(tid);
}
close(server);
return 0;
}
void* cil(void* arg)
{
int client = ((Cli_msg*)arg)->client;
struct sockaddr_in caddr = ((Cli_msg*)arg)->caddr;
char buf[128] = "";
int res = 0;
while(1)
{
bzero(buf, sizeof(buf));
if((res = read(client, buf, sizeof(buf))) < 0)
{
LOG("read error");
break;
}
else if(res == 0)
{
printf("[%s/%d]client已下线\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));
close(client);
pthread_exit(NULL);
}
printf("[%s/%d]client: %s\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port), buf);
bzero(buf, sizeof(buf));
strcpy(buf, "ok");
if(write(client, buf, sizeof(buf)) < 0)
{
LOG("write error");
break;
}
}
}