1.17 第四章+第五章 多点通信+域套接字

发布时间:2024年01月18日

思维导图

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;
}

文章来源:https://blog.csdn.net/2301_80922669/article/details/135657814
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。