在前面TCP网络编程代码的基础上进行改造,实现并发服务器功能。
TCP多线程服务器
实现功能:
- server端可以绑定在任意IP端
- server端停止使用crtl+p
- client端运行./client时需加上(ip_addr, netport)
- 支持多client链接
- server端可打印client的ip地址和端口号
server端代码
#include "net.h"
#include <pthread.h>
typedef struct client_info{
int newfp;
char ipv4_addr[14];
int port;
}Client_info, *pClient_info ;
void * process(pClient_info arg);
int main()
{
int fp;
struct sockaddr_in myaddr;
if((fp = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket fail");
exit(0);
}
memset(&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_port = htons(Netport);
myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(fp,(struct sockaddr*) &myaddr,sizeof(myaddr)) < 0)
{
perror("bind fail");
exit(0);
}
if(listen(fp, BACKLOG) < 0)
{
perror("listen fail");
exit(0);
}
int newfp = -1;
struct sockaddr_in recv_addr;
socklen_t recv_addr_len = sizeof(recv_addr);
while(1)
{
newfp = accept(fp, (struct sockaddr *)&recv_addr, (socklen_t *)&recv_addr_len);
if(newfp < 0)
{
perror("accept fail");
exit(0);
}
Client_info cin;
bzero(cin.ipv4_addr, 16);
if(NULL == inet_ntop(AF_INET,(void *)&recv_addr.sin_addr, cin.ipv4_addr, sizeof(recv_addr)))
{
perror("inet_ntop");
exit(0);
}
cin.port = ntohs(recv_addr.sin_port);
cin.newfp = newfp;
printf("success the connet !\n");
printf("connect ip address = %s, connect port = %d \n",cin.ipv4_addr, cin.port);
pthread_t tid;
if(pthread_create(&tid, NULL, (void *)(process), &cin) != 0)
{
perror("thread fail");
exit(0);
}
}
close(newfp);
close(fp);
return 0;
}
void * process(pClient_info cin)
{
pthread_detach(pthread_self());
int newfp = cin->newfp;
char ipv4_addr[16] = {0};
strcpy(ipv4_addr, cin->ipv4_addr);
int port = cin->port;
char buf[BUFSIZ];
bzero(buf,BUFSIZ);
int ret = -1;
while(1)
{
do{
ret = read(newfp, buf, BUFSIZ-1);
}while(ret<0 && errno == EINTR);
if(ret < 0)
{
perror("read fail");
exit(1);
}
if(ret == 0)
{
break;
}
if(!strncmp(buf,QUIT_STR,strlen(QUIT_STR)))
{
printf("Client is exiting !\n");
break;
}
if(!strncmp(buf,"\n",1))
{
bzero(buf,BUFSIZ);
}
printf("(%s : %d): %s \n", ipv4_addr, port,buf);
}
close(newfp);
pthread_exit(NULL);
pthread_join(pthread_self(),NULL);
return NULL;
}
client端代码
#include "net.h"
int main(int argc, char* argcv[])
{
if(argc != 3)
{
printf("enter error!\n");
printf("please fill:ip_addr, netport \n");
exit(0);
}
int fp = -1;
if((fp = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket fail");
exit(0);
}
struct sockaddr_in myaddr;
memset(&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
int netport = atoi(argcv[2]);
if(netport < 50000)
{
netport = Netport;
}
myaddr.sin_port = htons(netport);
if(inet_pton(AF_INET, argcv[1], (void *)&myaddr.sin_addr.s_addr) != 1)
{
perror("inet_pton fail");
exit(0);
}
if(connect(fp,(struct sockaddr *)&myaddr, sizeof(myaddr)) < 0)
{
perror("connect fail");
exit(0);
}
char buf[BUFSIZ];
while(1)
{
bzero(buf,BUFSIZ);
if(fgets(buf, BUFSIZ, stdin) == NULL)
{
continue;
}
write(fp, buf, strlen(buf));
if(!strncmp(buf,QUIT_STR, strlen(QUIT_STR)))
{
printf("Client is exiting !\n");
break;
}
}
close(fp);
return 0;
}
net.h头文件
#ifndef __NET_H__
#define __NET_H__
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <arpa/inet.h>
#define Netport 50001
#define Netip "XXX.XXX.XXX.XXX"
#define BACKLOG 5
#define QUIT_STR "quit"
#endif
TCP多进程服务器
server端
采用SIGCHLD信号来回收子进程。
#include "net.h"
#include <pthread.h>
#include <signal.h>
#include <sys/wait.h>
typedef struct client_info{
int newfp;
char ipv4_addr[14];
int port;
}Client_info, *pClient_info ;
void * process(pClient_info arg);
void cil_data_handle(int signum);
int main()
{
signal(SIGCHLD, cil_data_handle);
int fp;
struct sockaddr_in myaddr;
if((fp = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket fail");
exit(0);
}
memset(&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_port = htons(Netport);
myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(fp,(struct sockaddr*) &myaddr,sizeof(myaddr)) < 0)
{
perror("bind fail");
exit(0);
}
if(listen(fp, BACKLOG) < 0)
{
perror("listen fail");
exit(0);
}
int newfp = -1;
struct sockaddr_in recv_addr;
socklen_t recv_addr_len = sizeof(recv_addr);
while(1)
{
newfp = accept(fp, (struct sockaddr *)&recv_addr, (socklen_t *)&recv_addr_len);
if(newfp < 0)
{
perror("accept fail");
exit(0);
}
Client_info cin;
bzero(cin.ipv4_addr, 16);
if(NULL == inet_ntop(AF_INET,(void *)&recv_addr.sin_addr, cin.ipv4_addr, sizeof(recv_addr)))
{
perror("inet_ntop");
exit(0);
}
cin.port = ntohs(recv_addr.sin_port);
cin.newfp = newfp;
printf("success the connet !\n");
printf("connect ip address = %s, connect port = %d \n",cin.ipv4_addr, cin.port);
pid_t pid;
if((pid = fork()) < 0 )
{
perror("fork fail");
exit(0);
}
else if(pid == 0)
{
close(fp);
process(&cin);
return 0;
}
else
{
close(newfp);
}
}
close(fp);
return 0;
}
void * process(pClient_info cin)
{
pthread_detach(pthread_self());
int newfp = cin->newfp;
char ipv4_addr[16] = {0};
strcpy(ipv4_addr, cin->ipv4_addr);
int port = cin->port;
char buf[BUFSIZ];
bzero(buf,BUFSIZ);
int ret = -1;
while(1)
{
do{
ret = read(newfp, buf, BUFSIZ-1);
}while(ret<0 && errno == EINTR);
if(ret < 0)
{
perror("read fail");
exit(1);
}
if(ret == 0)
{
break;
}
if(!strncmp(buf,QUIT_STR,strlen(QUIT_STR)))
{
printf("Client is exiting !\n");
break;
}
if(!strncmp(buf,"\n",1))
{
bzero(buf,BUFSIZ);
}
printf("(%s : %d): %s \n", ipv4_addr, port,buf);
}
close(newfp);
return NULL;
}
void cil_data_handle(int signum)
{
if(signum == SIGCHLD)
{
waitpid(-1, NULL, WNOHANG);
}
}
client端
#include "net.h"
int main(int argc, char* argcv[])
{
if(argc != 3)
{
printf("enter error!\n");
printf("please fill:ip_addr, netport \n");
exit(0);
}
int fp = -1;
if((fp = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket fail");
exit(0);
}
struct sockaddr_in myaddr;
memset(&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
int netport = atoi(argcv[2]);
if(netport < 50000)
{
netport = Netport;
}
myaddr.sin_port = htons(netport);
if(inet_pton(AF_INET, argcv[1], (void *)&myaddr.sin_addr.s_addr) != 1)
{
perror("inet_pton fail");
exit(0);
}
if(connect(fp,(struct sockaddr *)&myaddr, sizeof(myaddr)) < 0)
{
perror("connect fail");
exit(0);
}
char buf[BUFSIZ];
while(1)
{
bzero(buf,BUFSIZ);
if(fgets(buf, BUFSIZ, stdin) == NULL)
{
continue;
}
write(fp, buf, strlen(buf));
if(!strncmp(buf,QUIT_STR, strlen(QUIT_STR)))
{
printf("Client is exiting !\n");
break;
}
}
close(fp);
return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)