思维导图
TCP多进程并发服务器
网络编程实现,一个服务器,一个客户端的通信;多进程并发;父进程非阻塞回收子进程资源
代码
#include<myhead.h>
#define SER_IP "172.20.10.3" //服务器ip地址 虚拟机的
#define SER_PORT 8888
void handler(int signum)
{
//判断 捕获到的信号是SIGCHLD
if(signum == SIGCHLD)
{
//以非阻塞的方式回收僵尸进程
while(waitpid(-1,NULL,WNOHANG)>0);
}
}
/****************main function***************/
int main()
{
//绑定SIGCHLD信号到处理函数中
if(signal(SIGCHLD,handler)==SIG_ERR)
{
perror("signal error");
return -1;
}
//1.创建一个用于连接的 套接字描述符
int sfd = socket(AF_INET,SOCK_STREAM,0);
if (sfd == -1)
{
perror("socket error");
return -1;
}
printf("sfd = %d\n",sfd);
//套接字 设置 端口快速重用
int reuse =1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))==-1)
{
perror("setsockopr error");
return -1;
}
printf("端口已快速重用\n");
//2.给套接字绑定ip地址和端口号
//2.1 准备地址信息结构体
struct sockaddr_in sin;
sin.sin_family = AF_INET;//通信域地址族
sin.sin_port = htons(SER_PORT);//服务器端口号
sin.sin_addr.s_addr = inet_addr(SER_IP);
//2.2 执行绑定工作
if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))==-1)
{
perror("bind error");
return -1;
}
printf("bind success");
//3.将套接字 设置 被动监听状态
if(listen(sfd,128)==-1)
{
perror("listen error");
return -1;
}
printf("listen success\n");
//4.阻塞等候 客户端的连接
//4.1定义地址信息结构体,用于接收客户端地址信息
struct sockaddr_in cin;
socklen_t addrlen=sizeof(cin); //接收地址长度
while(1)
{
//阻塞等待客户端连接
int newfd = accept(sfd,(struct sockaddr*)&cin,&addrlen);
if(newfd ==-1)
{
perror("accept error");
return -1;
}
printf("[%s:%d]-连接成功newfd = %d\n",\
inet_ntoa(cin.sin_addr),\
ntohs(cin.sin_port),newfd);
//客户端连接成功 创建子进程用于通信
pid_t pid=fork();
//判断父进程
if(pid>0)
{
//父进程
//不需要用到newfd,关闭
close(newfd);
}
else if(pid ==0)
{
//用不到sfd,关闭
close(sfd);
//5.实现数据的的收发
char buf[128]="";
while(1)
{
//清空buf
bzero(buf,sizeof(buf));
//从套接字 中 读取消息
int res = recv(newfd,buf,sizeof(buf),0);
if(res==0)
{
printf("客户端已下线\n");
close(newfd);
break;
}
printf("[%s:%d]:%s\n",\
inet_ntoa(cin.sin_addr),\
ntohs(cin.sin_port),buf);
//给消息加一个:D还回去
strcat(buf,":D");
send(newfd,buf,strlen(buf),0);
printf("发送成功\n");
}
}
}
//6.关闭套接字
close(sfd);
return 0;
}
TCP多线程并发服务器
网络编程实现,一个服务器,一个客户端的通信;多线程并发;线程分离,系统自动回收子线程的资源
代码
#include<myhead.h>
#define SER_IP "172.20.10.3" //服务器ip地址 虚拟机的
#define SER_PORT 8888
/****************main function***************/
int main()
{
//1.创建一个用于连接的 套接字描述符
int sfd = socket(AF_INET,SOCK_STREAM,0);
if (sfd == -1)
{
perror("socket error");
return -1;
}
printf("sfd = %d\n",sfd);
//套接字 设置 端口快速重用
int reuse =1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))==-1)
{
perror("setsockopr error");
return -1;
}
printf("端口已快速重用\n");
//2.给套接字绑定ip地址和端口号
//2.1 准备地址信息结构体
struct sockaddr_in sin;
sin.sin_family = AF_INET;//通信域地址族
sin.sin_port = htons(SER_PORT);//服务器端口号
sin.sin_addr.s_addr = inet_addr(SER_IP);
//2.2 执行绑定工作
if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))==-1)
{
perror("bind error");
return -1;
}
printf("bind success");
//3.将套接字 设置 被动监听状态
if(listen(sfd,128)==-1)
{
perror("listen error");
return -1;
}
printf("listen success\n");
//4.阻塞等候 客户端的连接
//4.1定义地址信息结构体,用于接收客户端地址信息
struct sockaddr_in cin;
socklen_t addrlen=sizeof(cin); //接收地址长度
while(1)
{
int newfd = accept(sfd,(struct sockaddr*)&cin,&addrlen);
if(newfd ==-1)
{
perror("accept error");
return -1;
}
printf("[%s:%d]-连接成功newfd = %d\n",\
inet_ntoa(cin.sin_addr),\
ntohs(cin.sin_port),newfd);
//5.实现数据的的收发
char buf[128]="";
while(1)
{
//清空buf
bzero(buf,sizeof(buf));
//从套接字 中 读取消息
int res = recv(newfd,buf,sizeof(buf),0);
if(res==0)
{
printf("客户端已下线\n");
close(newfd);
break;
}
printf("[%s:%d]:%s\n",\
inet_ntoa(cin.sin_addr),\
ntohs(cin.sin_port),buf);
//给消息加一个:D还回去
strcat(buf,":D");
send(newfd,buf,strlen(buf),0);
printf("发送成功\n");
}
//6.关闭套接字
close(sfd);
return 0;
}
}
基于UDP的网络聊天室
没写出来,下一篇补充一下吧。 (╥﹏╥)