多进程实现tcp服务器链接多客户端
#include<stdio.h>
#include <sys/types.h>
#include<string.h>
#include<stdlib.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include<unistd.h>
#include <signal.h>
#include <sys/wait.h>
//进程实现tcp服务器链接多客户端
#define ERR_MSG(msg) do{\
fprintf(stderr,"line :%d\n",__LINE__);\
perror("msg");\
}while(0)
#define IP "192.168.0.105"
void handler(int arg)
{
while(waitpid(-1,NULL,WNOHANG) > 0);
}
int main(int argc, const char *argv[])
{
//接收子进程状态改变信号
__sighandler_t s = signal(SIGCHLD ,handler);
if(s == SIG_ERR)
{
ERR_MSG("signal");
return -1;
}
int sfd = socket(AF_INET,SOCK_STREAM,0);
if(sfd < 0)
{
ERR_MSG("socket");
return -1;
}
//允许端口快速被重复使用
int reuse = 1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)) < 0)
{
ERR_MSG("setsockopt");
return -1;
}
printf("允许端口快速复用\n");
//定义地址信息结构体
struct sockaddr_in my_addr;
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(8888);
my_addr.sin_addr.s_addr = inet_addr(IP);
struct sockaddr_in peer_addr;
socklen_t addrlen = sizeof(peer_addr);
//绑定地址信息结构体
if(bind(sfd,(struct sockaddr *)&my_addr,sizeof(my_addr)) < 0)
{
ERR_MSG("bind");
return -1;
}
printf("success to bind line:%d\n",__LINE__);
//设置被动监听模式
int backlog = 128;
int newfd;
if(listen(sfd,backlog) < 0)
{
ERR_MSG("listen");
return -1;
}
printf("success to listen. line:%d\n",__LINE__);
int pid;
char buf[128] = "";
int res;
while(1)
{
//接收客户端请求并存储客户端信息
newfd = accept(sfd,(struct sockaddr *)&peer_addr,&addrlen);
if(newfd < 0)
{
ERR_MSG("accept");
return -1;
}
printf("success to accept. line:%d\n",__LINE__);
pid = fork();
if(pid < 0)
{
ERR_MSG("fork");
return -1;
}else if(0 == pid)
{
while(1)
{
close(sfd);
bzero(buf,sizeof(buf));
//接收
res = recv(newfd ,buf,sizeof(buf),0);
if(res < 0)
{
ERR_MSG("recv");
break;
}
if(0 == res)
{
printf("[%s:%d] newfd = %d 客户端下线__%d__\n",inet_ntoa(peer_addr.sin_addr),\
ntohs(peer_addr.sin_port),newfd, __LINE__);
break;
}
printf("[%s:%d] newfd = %d %s __%d__\n",inet_ntoa(peer_addr.sin_addr),\
ntohs(peer_addr.sin_port),newfd,buf , __LINE__);
//发送
strcat(buf,"*_*");
if(send(newfd,buf,sizeof(buf),0) < 0)
{
ERR_MSG("send");
break ;
}
}
close(newfd);
exit(0);
}else if(pid > 0)
{
close(newfd);
}
}
return 0;
}
多线程实现tcp服务器链接多客户端
#include<stdio.h>
#include <sys/types.h>
#include<string.h>
#include<stdlib.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include<unistd.h>
#include <pthread.h>
#include <errno.h>
//线程实现tcp服务器链接多客户端
#define ERR_MSG(msg) do{\
fprintf(stderr,"line :%d\n",__LINE__);\
perror("msg");\
}while(0)
#define IP "192.168.0.105"
struct massage
{
int newfd;
struct sockaddr_in peer_addr;
};
void *deal_msg(void *arg);
int main(int argc, const char *argv[])
{
int sfd = socket(AF_INET,SOCK_STREAM,0);
if(sfd < 0)
{
ERR_MSG("socket");
return -1;
}
//允许端口快速被重复使用
int reuse = 1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)) < 0)
{
ERR_MSG("setsockopt");
return -1;
}
printf("允许端口快速复用\n");
//定义地址信息结构体
struct sockaddr_in my_addr;
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(8888);
my_addr.sin_addr.s_addr = inet_addr(IP);
struct sockaddr_in peer_addr;
socklen_t addrlen = sizeof(peer_addr);
//绑定地址信息结构体
if(bind(sfd,(struct sockaddr *)&my_addr,sizeof(my_addr)) < 0)
{
ERR_MSG("bind");
return -1;
}
printf("success to bind line:%d\n",__LINE__);
//设置被动监听模式
int backlog = 128;
int newfd;
if(listen(sfd,backlog) < 0)
{
ERR_MSG("listen");
return -1;
}
printf("success to listen. line:%d\n",__LINE__);
pthread_t tid;
int ret;
struct massage mg;
while(1)
{
//接收客户端请求并存储客户端信息
newfd = accept(sfd,(struct sockaddr *)&peer_addr,&addrlen);
if(newfd < 0)
{
ERR_MSG("accept");
return -1;
}
mg.newfd = newfd;
mg.peer_addr = peer_addr;
printf("success to accept. line:%d\n",__LINE__);
ret = pthread_create(&tid,NULL,deal_msg, &mg);
if(ret != 0)
{
errno = ret;
perror("pthread_create");
return -1;
}
pthread_detach(tid);
}
return 0;
}
void *deal_msg(void *arg)
{
int res;
char buf[128] = "";
int newfd = ((struct massage *)arg)->newfd;
struct sockaddr_in peer_addr = ((struct massage*)arg)->peer_addr;
while(1)
{
bzero(buf,sizeof(buf));
//接收
res = recv(newfd ,buf,sizeof(buf),0);
if(res < 0)
{
ERR_MSG("recv");
break;
}
if(0 == res)
{
printf("[%s:%d] newfd = %d 客户端下线__%d__\n",inet_ntoa(peer_addr.sin_addr),\
ntohs(peer_addr.sin_port),newfd, __LINE__);
break;
}
printf("[%s:%d] newfd = %d %s __%d__\n",inet_ntoa(peer_addr.sin_addr),\
ntohs(peer_addr.sin_port),newfd,buf , __LINE__);
//发送
strcat(buf,"*_*");
if(send(newfd,buf,sizeof(buf),0) < 0)
{
ERR_MSG("send");
break ;
}
}
close(newfd);
pthread_exit(NULL);
}