一 TCP并发服务器补充
用frok函数创建让子进程工作
1服务器端
1 为了防止僵尸进程 要在栈区开辟空间 回收子进程
2 用frok函数创建让子进程工作
(kill 序号17 为回收信号)
#include<stdio.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<string.h>
#include<stdlib.h>
#include<pthread.h>
void child(void *arg);//声明
void kill_wait(int num)
{
if(num==SIGCHLD)
{
waitpid(-1,NULL,WNOHANG);
}
}
int main()
{
int fd =-1;
struct sockaddr_in sin;
fd=socket(AF_INET,sock_stream,0);
kill_wait(SIGCHID);
if(fd<0)
{
perror("socket");
exit(1);
}
bzero(&sin,sizeof(sin));
sin.sin_family=AF_INET;
sin.sin_port=htons(5003);
// sin.sin_addr.s_addr=inet_addr("192.168.2129");
sin.sin_addr.s_addr=INADDR_INY;
if(bind(fd,(struct sockaddr *)&sin,sizeof(sin))<0)
{
perror("bind");
exit(1);
}
if(listen(fd,5)<0)
{
perror("listen");
exit(1);
}
int newfd=-1;
char buf[1024];
struct sockaddr_in cin;
socklen len=sizeof(cin);
pid_t pid;
while(1)
{
newfd=accept(fd,(struct sockaddr* )&cin,&len);//&ci哪里都存有端口号和 i 地址了但是现在为网络字节序 需要转为主机字节序
if(newfd<0)
{
perror("accept");
exit(1);
}
char ipv4_buf[16];//比如 192.168.2.129+'/' ==14个字符 所以数组不要过多大这个大小
if(!inet_ntop(AF_INET,(void *)&cin.sin_addr.s_addr,ipv4_buf,sizeof(cin)))
{
perror("inet_ntop");
exit(1);
}
printf("IPV4=====%s port====%d\n",ipv4_buf,ntohs(cin.sin_port));
//ntohs函数网络字节序转为主机字节序
pid=fork();
if(pid<0)
{
break;
}
if(pid==0)
{
close(fd);
child(&newfd);// 子进程工作
}
if(pid>0)
{
close(newfd);
}
}
close(fd);
close(newfd);
return 0;
}
void child(void *arg)
{
char buf[1024];
int rts=-1;
int newfd=*(int *)arg;
while(1)
{
do
{
bzero(buf,1024);
rts=read(newfd,buf,1023);
}while(rts<1);//while(rts<1);==rts>1
if(rts<0)
{
exit(1);
}
if(rts==0)
{
break;
}
printf("read is %s\n",buf);
}
close(fd);
close(newfd);
}
二 客户端
#include<stdio.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<string.h>
#include<stdlib.h>
int main(int argc,char **argv)
{
int fd =-1;
struct sockaddr_in sin;
if(argc!=3)
{
exit(1);
}
int port =atoi(argv[2]);
//XXXX 192.186.2.129 5003
fd=socket(AF_INET,sock_stream,0);
if(fd<0)
{
perror("socket");
exit(1);
}
bzero(&sin,sizeof(sin));
sin.sin_family=AF_INET;
sin.sin_port=htons(port);
sin.sin_addr.s_addr=inet_addr(argv[1]);
//XXXX 192.186.2.129 5003
if(connect(fd,(struct sockaddr*)&sin,sizeof(sin))<0)
{
perror("connect");
exit(1);
}
char buf[1024];
while(1)
{
bzero(buf,1024);
if(fgets(buf,1023,stdin)==NULL)
{
continue;
}
write(fd,buf,sizeof(buf));
}
return 0;
}
UDP客户端和服务器
基本流程都一样
UDP 是不可靠传输 不用 listen函数主动转为被动 不用accept 阻塞等待
因为他的发送不需要考虑缓存问题 只管发送 不考虑 接收的问题
服务器:修改对应的套接字类型
因为不需要考虑缓存问题 所以 要重映射函数 不断换输出位置
读取函数也有所修改 不过差别不大
服务器
recvfrom函数
先 知道recvfrom函数 用法 上面有链接
#include<stdio.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<string.h>
#include<stdlib.h>
#include<pthread.h>
#include<strings.h>
int main()
{
int fd =-1;
struct sockaddr_in sin;
fd=socket(AF_INET,SOCK_DGRAM,0);
if(fd<0)
{
perror("socket");
exit(1);
}
int ys=-1;
// 重映射
setsockopt(fd,SOL_SOCKET,SO_REUSEADR,&ys,sizeof(int));//先用 别纠结
bzero(&sin,sizeof(sin));
sin.sin_family=AF_INET;
sin.sin_port=htons(6000);
// sin.sin_addr.s_addr=inet_addr("192.168.2129");
sin.sin_addr.s_addr=INADDR_INY;
int newfd=-1;
char buf[1024];
struct sockaddr_in cin;
socklen len=sizeof(cin);
while(1)
{
bzero(buf,1024);
if(recvfrom(fd,buf,1023,0,(struct sockaddr *)&cin,&len)<0)
{
perror("recvfrom");
continue;//没数据 就退出一次
}
char ipv4_buf[16];//比如 192.168.2.129+'/' ==14个字符 所以数组不要过多大这个大小
if(!inet_ntop(AF_INET,(void *)&cin.sin_addr.s_addr,ipv4_buf,sizeof(cin)))
{
perror("inet_ntop");
exit(1);
}
printf("IPV4=====%s port====%d data is %s\n",ipv4_buf,ntohs(cin.sin_port),buf);
//ntohs函数网络字节序转为主机字节序
}
close(fd);
close(newfd);
return 0;
}
客户端
sendto函数
先 知道send 函数 用法 上面有链接
#include<stdio.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<string.h>
#include<stdlib.h>
int main(int argc,char **argv)
{
int fd =-1;
struct sockaddr_in sin;
if(argc!=3)
{
exit(1);
}
int port =atoi(argv[2]);
//XXXX 192.186.2.129 5003
fd=socket(AF_INET,SOCK_DGRAM,0);
if(fd<0)
{
perror("socket");
exit(1);
}
bzero(&sin,sizeof(sin));
sin.sin_family=AF_INET;
sin.sin_port=htons(port);
sin.sin_addr.s_addr=inet_addr(argv[1]);
//XXXX 192.186.2.129 5003
char buf[1024];
while(1)
{
bzero(buf,1024);
if(fgets(buf,1023,stdin)==NULL)
{
continue;
}
sendto(fd,buf,1024,(struct sockaddr *)&sin,sizeof(sin));
}
return 0;
}
可以实现 验证成功