多进程
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <signal.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/socket.h>
//服务器
#define ERR_MSG(msg) do{\
fprintf(stderr,"line:%d ",__LINE__);\
perror("msg");\
}while(0)
#define PORT 8888
#define IP "192.168.110.73"
int deal_msg(int newfd,struct sockaddr_in peer_addr);
void handler(int arg)
{
while(waitpid(-1,NULL,WNOHANG) > 0);
}
int main(int argc, const char *argv[])
{
//接收状态改变信号,创建函数处理
__sighandler_t s = signal(SIGCHLD,handler);
int sfd = socket(AF_INET,SOCK_STREAM,0);
if(sfd < 0)
{
ERR_MSG("socket");
return -1;
}
printf("success to socket. line : %d\n",__LINE__);
//允许端口快速复用
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(PORT);
my_addr.sin_addr.s_addr = inet_addr(IP);
//绑定地址信息结构体
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;
if(listen(sfd,backlog) < 0)
{
ERR_MSG("listen");
return -1;
}
printf("success to listen. line : %d\n",__LINE__);
//创建地址信息结构体存放服务器信息
struct sockaddr_in peer_addr;
socklen_t addrlen = sizeof(peer_addr);
//父进程循环接收连接请求
//子进程负责交互
pid_t pid;
while(1)
{
int newfd = accept(sfd,(struct sockaddr *)&peer_addr,&addrlen);
if(newfd < 0)
{
ERR_MSG("accept");
return -1;
}
printf("success to accept. line : %d\n",__LINE__);
printf("IP:%s PORT:%d\n",inet_ntoa(peer_addr.sin_addr),ntohs(peer_addr.sin_port));
pid = fork();
if(pid < 0)
{
ERR_MSG("fork");
return -1;
}else if(0 == pid)
{
close(sfd);
deal_msg(newfd,peer_addr);
exit(0);
}else if(pid > 0)
{
close(newfd);
}
}
close(sfd);
return 0;
}
int deal_msg(int newfd,struct sockaddr_in peer_addr)
{
char buf[128] = "";
int res;
while(1)
{
bzero(buf,sizeof(buf));
//接收消息
res = recv(newfd,buf,sizeof(buf),0);
if(res < 0)
{
ERR_MSG("res");
return -1;
}else if(0 == res)
{
printf("IP:%s PORT:%d 客户端下线\n",inet_ntoa(peer_addr.sin_addr),\
ntohs(peer_addr.sin_port));
close(newfd);
exit(0);
}
printf("IP:%s PORT:%d msg:%s\n",inet_ntoa(peer_addr.sin_addr),\
ntohs(peer_addr.sin_port),buf);
//发送消息
strcat(buf,"*_*");
if(send(newfd,buf,sizeof(buf),0) < 0)
{
ERR_MSG("send");
return -1;
}
}
return 0;
}
多线程
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <unistd.h>
#include <sys/socket.h>
#include <pthread.h>
//服务器
#define ERR_MSG(msg) do{\
fprintf(stderr,"line:%d ",__LINE__);\
perror("msg");\
}while(0)
#define PORT 9999
#define IP "192.168.110.74"
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;
}
printf("success to socket. line : %d\n",__LINE__);
//允许端口快速复用
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(PORT);
my_addr.sin_addr.s_addr = inet_addr(IP);
//绑定地址信息结构体
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;
if(listen(sfd,backlog) < 0)
{
ERR_MSG("listen");
return -1;
}
printf("success to listen. line : %d\n",__LINE__);
//创建地址信息结构体存放服务器信息
struct sockaddr_in peer_addr;
socklen_t addrlen = sizeof(peer_addr);
//父进程循环接收连接请求
//子进程负责交互
pthread_t tid;
while(1)
{
int newfd = accept(sfd,(struct sockaddr *)&peer_addr,&addrlen);
if(newfd < 0)
{
ERR_MSG("accept");
return -1;
}
printf("success to accept. line : %d\n",__LINE__);
printf("IP:%s PORT:%d\n",inet_ntoa(peer_addr.sin_addr),ntohs(peer_addr.sin_port));
struct massage fdmag;
fdmag.newfd = newfd;
fdmag.peer_addr = peer_addr;
if(pthread_create(&tid,NULL,deal_msg,(void *)&fdmag) !=0)
{
fprintf(stderr,"line:%d ",__LINE__);
return -1;
}
pthread_detach(tid);
}
close(sfd);
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("res");
break ;
}else if(0 == res)
{
printf("IP:%s PORT:%d 客户端下线\n",inet_ntoa(peer_addr.sin_addr),\
ntohs(peer_addr.sin_port));
close(newfd);
exit(0);
}
printf("IP:%s PORT:%d msg:%s\n",inet_ntoa(peer_addr.sin_addr),\
ntohs(peer_addr.sin_port),buf);
//发送消息
strcat(buf,"*_*");
if(send(newfd,buf,sizeof(buf),0) < 0)
{
ERR_MSG("send");
break ;
}
}
close(newfd);
pthread_exit(NULL);
}