思维导图
1.广播
服务器端:
#include<header.h>
int main(int argc, const char *argv[])
{
//1.创建广播接收端
int rfd=socket(AF_INET,SOCK_DGRAM,0);
if(rfd==-1)
{
perror("socket error");
return -1;
}
//2.填充地址信息结构体
struct sockaddr_in rin;
rin.sin_family=AF_INET;
rin.sin_port=htons(6789);
rin.sin_addr.s_addr=inet_addr("192.168.125.255");//广播地址
//3.绑定
if(bind(rfd,(struct sockaddr*)&rin,sizeof(rin))==-1)
{
perror("bind error");
return -1;
}
//4.接受信息
char rbuf[128]="";
while(1)
{
bzero(rbuf,sizeof(rbuf));//清空数组
recvfrom(rfd,rbuf,sizeof(rbuf),0,0,0);//接收信息
printf("收到消息为:%s\n",rbuf);
if(strcmp(rbuf,"quit")==0)//收到quit后退出循环
break;
}
//5.关闭套接字
close(rfd);
return 0;
}
ubu
?客户端:
#include<header.h>
int main(int argc, const char *argv[])
{
//1.创建套接字
int sfd=socket(AF_INET,SOCK_DGRAM,0);
if(sfd==-1)
{
perror("socket error");
return -1;
}
//2.将套接字设置成允许广播
int broadcast=1;
if(setsockopt(sfd,SOL_SOCKET,SO_BROADCAST,&broadcast,sizeof(broadcast))==-1)
{
perror("setsockopt error");
return -1;
}
//3.可绑定可不绑定
//4.填充接收端地址信息结构体
struct sockaddr_in cin;
cin.sin_family=AF_INET;
cin.sin_port=htons(6789);
cin.sin_addr.s_addr=inet_addr("192.168.125.255");
//5.发送信息
char sbuf[128]="";
while(1)
{
printf("请输入>>>>");
fgets(sbuf,sizeof(sbuf),stdin);
sbuf[strlen(sbuf)-1]='\0';
sendto(sfd,sbuf,sizeof(sbuf),0,(struct sockaddr*)&cin,sizeof(cin));
puts("发送成功");
if(strcmp(sbuf,"quit")==0)
break;
}
//6.关闭套接字
close(sfd);
return 0;
}
2.组播
服务器端
#include<header.h>
int main(int argc, const char *argv[])
{
//1.创建套接字
int rfd=socket(AF_INET,SOCK_DGRAM,0);
if(rfd==-1)
{
perror("socket error");
return -1;
}
//2.设置网络属性
struct ip_mreqn im;
im.imr_multiaddr.s_addr=inet_addr("224.1.2.3");//组播地址
im.imr_address.s_addr=inet_addr("192.168.124.57");
im.imr_ifindex=2;
if(setsockopt(rfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&im,sizeof(im))==-1)
{
perror("setsockopt error");
return -1;
}
puts("成功加入多播组");
//3.填充地址信息结构体
struct sockaddr_in rin;
rin.sin_family=AF_INET;
rin.sin_port=htons(9999);
rin.sin_addr.s_addr=inet_addr("224.1.2.3");
//4.绑定
if(bind(rfd,(struct sockaddr*)&rin,sizeof(rin))==-1)
{
perror("bind error");
return 1;
}
//5.接收信息
char rbuf[128]="";
while(1)
{
bzero(rbuf,sizeof(rbuf));
recvfrom(rfd,rbuf,sizeof(rbuf),0,0,0);
printf("收到谢谢为:%s\n",rbuf);
}
//6.关闭套接字
close(rfd);
return 0;
}
客户端
#include<header.h>
int main(int argc, const char *argv[])
{
//创建套接字
int sfd=socket(AF_INET,SOCK_DGRAM,0);
if(sfd==-1)
{
perror("socket error");
return -1;
}
//2.绑定,可不绑定
//3.填充地址信息结构体
struct sockaddr_in sin;
sin.sin_family=AF_INET;
sin.sin_port=htons(9999);
sin.sin_addr.s_addr=inet_addr("224.1.2.3");
//4.收发数据
char sbuf[128]="";
while(1)
{
bzero(sbuf,sizeof(buf));
printf("请输入>>>>");
fgets(sbuf,sizeof(sbuf),stdin);
sbuf[strlen(sbuf)-1]='\0';
//发送信息
sendto(sfd,sbuf,sizeof(sbuf),0,(struct sockaddr*)&sin,sizeof(sin));
puts("发送成功");
}
//5.关闭套接字
close(sfd);
return 0;
}
3.流式域套接字
服务器端
#include<header.h>
int main(int argc, const char *argv[])
{
//1.创建套接字
int sfd=socket(AF_UNIX,SOCK_STREAM,0);
if(sfd==-1)
{
perror("socket error");
return -1;
}
//判断套接字文件是否存在,若存在则删除
if(access("./unix",F_OK)==0)
{
if(unlink("./unix")==-1)//执行删除指令
{
perror("unlink error");
return -1;
}
}
//2.填充地址信息结构体
struct sockaddr_un sun;
sun.sun_family=AF_UNIX;//通信域
strcpy(sun.sun_path,"./unix");
//3.绑定地址信息结构体
if(bind(sfd,(struct sockaddr*)&sun,sizeof(sun))==-1)
{
perror("bind error");
return -1;
}
puts("bind success");
//4.设置监听
if(listen(sfd,128)==-1)
{
perror("listen error");
return -1;
}
//5.阻塞接收客户端连接请求
//定义容器接收客户端地址信息结构体
struct sockaddr_un cun;
socklen_t socklen=sizeof(cun);
int newfd=accept(sfd,(struct sockaddr*)&cun,&socklen);
if(newfd==-1)
{
perror("listen error");
return -1;
}
//6.收发数据
char buf[128]="";
while(1)
{
bzero(buf,sizeof(buf));//清空数组
int res=recv(newfd,buf,sizeof(buf),0);//读取信息
if(res==0)
{
puts("客户端已下线");
break;
}
printf("[%s]:%s\n",cun.sun_path,buf);
}
//7.关闭套接字
close(newfd);
close(sfd);
return 0;
}
客户端
#include<header.h>
#define CLI_PORT 6666
#define CLI_IP "192.168.122.70"
int main(int argc, const char *argv[])
{
//1.创建用于通信的套接字文件描述符
int cfd=socket(AF_UNIX,SOCK_STREAM,0);
if(cfd==-1)
{
perror("socket error");
return -1;
}
printf("cfd=%d\n",cfd);
if(access("./linux",F_OK)==0)
{
if(unlink("./linux")==-1)
{
perror("unlink error");
return -1;
}
}
//2.可不绑定
//2.1 填充地址信息结构体
struct sockaddr_un cun;
cun.sun_family=AF_UNIX;
strcpy(cun.sun_path,"./linux");
//2.2 绑定
if(bind(cfd,(struct sockaddr*)&cun,sizeof(cun))==-1)
{
perror("bind error");
return -1;
}
puts("bind success");
//3.连接服务器
//3.1填充要连接的服务器地址
struct sockaddr_un sun;
sun.sun_family=AF_UNIX;
strcpy(sun.sun_path,"./unix");
//3.2连接服务器
if(connect(cfd,(struct sockaddr*)&sun,sizeof(sun))==-1)
{
perror("connect error");
return -1;
}
puts("connect success");
//4.收发数据
char buf[128]="";
while(1)
{
bzero(buf,sizeof(buf));
printf("请输入>>>>>");
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1]='\0';
send(cfd,buf,sizeof(buf),0);
if(strcmp(buf,"quit")==0)
break;
printf("发送成功\n");
}
//5.关闭客户端
close(cfd);
return 0;
}
4.报式域套接字
服务器端
#include<header.h>
int main(int argc, const char *argv[])
{
//1.创建套接字
int sfd=socket(AF_UNIX,SOCK_DGRAM,0);
if(sfd==-1)
{
perror("socket error");
return -1;
}
printf("sfd=%d\n",sfd);
if(access("./linux",F_OK)==0)
{
if(unlink("./linux")==-1)
{
perror("unlink error");
return -1;
}
}
//2.绑定
//2.1填充地址信息结构体
struct sockaddr_un sun;
sun.sun_family=AF_UNIX;
strcpy(sun.sun_path,"./linux");
//2.2绑定
if(bind(sfd,(struct sockaddr*)&sun,sizeof(sun))==-1)
{
perror("bind error");
return -1;
}
puts("bind success");
//3.数据收发
char buf[128]="";
//定义变量存放客户端地址信息结构体
struct sockaddr_un cun;
socklen_t socklen=sizeof(cun);
while(1)
{
bzero(buf,sizeof(buf));//清空数组
recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&cun,&socklen);//从套接字文件中读取数据
printf("[%s]:%s\n",cun.sun_path,buf);
strcat(buf,"*_*");
if(sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&cun,sizeof(cun))==-1)
{
perror("sendto error");
return -1;
}
if(strcmp(buf,"quit")==0)
break;
puts("发送成功");
}
//4.关闭套接字
close(sfd);
return 0;
}
客户端
#include<header.h>
int main(int argc, const char *argv[])
{
//1.创建用于通信的套接字文件描述符
int cfd=socket(AF_UNIX,SOCK_DGRAM,0);
if(cfd==-1)
{
perror("socket error");
return -1;
}
if(access("./unix",F_OK)==0)
{
if(unlink("./unix")==-1)
{
perror("unlink,error");
return -1;
}
}
//2.可不绑定
struct sockaddr_un cun;
cun.sun_family=AF_UNIX;
strcpy(cun.sun_path,"./unix");
if(bind(cfd,(struct sockaddr*)&cun,sizeof(cun))==-1)
{
perror("bind error");
return -1;
}
//3.填充服务器的地址信息结构体
struct sockaddr_un sun;
sun.sun_family=AF_UNIX;
strcpy(sun.sun_path,"./linux");
//4.收发信息
char buf[128]="";
while(1)
{
printf("请输入>>>>");
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1]='\0';
//发送给服务器
sendto(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sun,sizeof(sun));
if(strcmp(buf,"quit")==0)
break;
//接收服务器发来的信息
recvfrom(cfd,buf,sizeof(buf),0,NULL,NULL);
printf("收到消息:%s\n",buf);
}
//5.关闭套接字
close(cfd);
return 0;
}
ub
5.TFTP文件传输
#include <header.h>
//上传功能
int do_upload(int sfd, struct sockaddr_in sin)
{
char filename[20] = "";
printf("请输入要上传的文件名>>>");
fgets(filename, 20, stdin);
filename[strlen(filename)-1] = 0;
//判断该文件是否存在
int fd = open(filename, O_RDONLY);
if(fd == -1)
{
if(errno == ENOENT)
{
printf("文件不存在,请重新输入!!!\n");
return -2;
}
else
{
perror("open error");
return -1;
}
}
//发送上传请求
//上传协议
char buf[516] = "";
int size = sprintf(buf, "%c%c%s%c%s%c", 0, 2, filename, 0, "octet", 0);
if(sendto(sfd, buf, size, 0, (struct sockaddr*)&sin, sizeof(sin))==-1)
{
perror("sendto error");
return -1;
}
//循环接收发送数据包
int recv_len;
unsigned short num = 0;
socklen_t socklen = sizeof(sin);
while(1)
{
bzero(buf, 516);
recv_len = recvfrom(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&sin, &socklen);
if(recv_len == -1)
{
perror("recvfrom error");
return -1;
}
//4 服务器返回应答包
if(4 == buf[1])
{
//判断当前数据包的编号是否等于应答包的编号
//防止数据包在传送过程丢包或重复收包
if(num == ntohs(*(unsigned short*)(buf+2)))
{
//修改操作码为数据包
buf[1] = 3;
//填充块编号
num++;
*(unsigned short*)(buf+2) = htons(num);
//读取数据
//发送数据
int res = read(fd, buf+4, 512);
if(res == -1)
{
perror("read error");
return -1;
}
else if(0 == res)
{
printf("文件上传完毕!!!\n");
break;
}
//发送数据包
//发送的数据包大小为,读取到的字节数(res)+操作码(2byte)+快编号(2byte)
if(sendto(sfd, buf, res+4, 0, (struct sockaddr*)&sin, sizeof(sin)) == -1)
{
perror("sendto error");
return -1;
}
}
else
{
printf("文件上传失败!!!\n");
break;
}
}
else if(5 == buf[1])
{
printf("ERROR:%s\n", buf+4);
break;
}
}
return 0;
}
//下载功能
int do_download(int sfd, struct sockaddr_in sin)
{
char filename[20] = "";
printf("请输入要下载的文件名>>>");
fgets(filename, 20, stdin);
filename[strlen(filename)-1] = 0;
//发送下载请求
char buf[516] = "";
int size = sprintf(buf, "%c%c%s%c%s%c", 0, 1, filename, 0, "octet", 0);
if(sendto(sfd, buf, size, 0, (struct sockaddr*)&sin, sizeof(sin)) == -1)
{
perror("sendto error");
return -1;
}
int flag = 0;
int fd ;
//循环接收发送应答包
ssize_t recv_len;
unsigned short num = 1;
socklen_t socklen = sizeof(sin);
while(1)
{
bzero(buf, 516);
recv_len = recvfrom(sfd, buf, 516, 0, (struct sockaddr*)&sin, &socklen);
if(recv_len == -1)
{
perror("recvfrom error");
return -1;
}
if(3 == buf[1])
{
if(0 == flag)
{
//存储从服务器下载下来的文件,接收数据成功后再创建数据;
//创建并打开filename文件
fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0664);
if(fd == -1)
{
perror("open error");
return -1;
}
flag = 1;
}
//判断当前的快编号,是否与我期望的快编号一致
if(htons(num) == *(unsigned short*)(buf+2)) //防止数据包重复到达
{
//提取数据,写入到文件中
if(write(fd, buf+4, recv_len-4) == -1)
{
printf("fd:%d recv_len=%ld\n", fd, recv_len);
perror("write error");
break;
}
//回复ack包
buf[1] = 4;
if(sendto(sfd, buf, 4, 0, (struct sockaddr*)&sin, sizeof(sin)) == -1)
{
perror("sendto error");
}
//判断数据包的大小是否小于 516;
if(recv_len < 516)
{
printf("文件下载完毕!!!\n");
break;
}
num++;
}
}
else if(5 == buf[1]) //错误包
{
//打印错误信息
printf("ERROR:%s\n", buf+4);
break;
}
}
return 0;
}
int main(int argc, const char *argv[])
{
if(argc < 2)
{
printf("请输入IP\n");
return -1;
}
//1.创建报式套接字
int sfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sfd == -1)
{
perror("socket");
return -1;
}
//2.填充服务器ip和端口号
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(8888);
sin.sin_addr.s_addr = inet_addr(argv[1]);
char menu;
while(1)
{
system("clear");
printf("******1.下载******\n");
printf("******2.上传******\n");
printf("******3.退出******\n");
scanf("%c", &menu);
while(getchar()!=10);
switch(menu)
{
case '1':
//下载功能, todo
do_download(sfd, sin);
break;
case '2':
//上传功能,todo
do_upload(sfd, sin);
break;
case '3':
goto END;
break;
default:
printf("输入错误,请重新输入!!!\n");
}
printf("请输入任意字符清屏>>>");
while(getchar()!=10);
}
//关闭文件描述符
END:
close(sfd);
return 0;
}