利用TCP/UDP 协议制作一个飞秋聊天工具 您所在的位置:网站首页 飞秋如何接收文件 利用TCP/UDP 协议制作一个飞秋聊天工具

利用TCP/UDP 协议制作一个飞秋聊天工具

2023-12-20 11:37| 来源: 网络整理| 查看: 265

 视频操作演示:

利用TCP/UDP 协议制作一个飞秋聊天工具演示视频

 

int udp_broadcast(char const*argv[]) { //1.创建对象 udp_socket = socket(AF_INET, SOCK_DGRAM, 0); if(udp_socketshare_file);//打印节点的共享文件信息 printf("请输入你要下载文件好友的文件\n"); scanf("%s",file); sprintf(pathname,"%s%s",p->pathname,file); //发送udp数据告诉好友 需要下载 //获取 好友 的 ip 和端口 struct sockaddr_in dest_addr; dest_addr.sin_family=AF_INET; //设置网络协议 dest_addr.sin_port=htons(udp_port); // dest_addr.sin_addr.s_addr=inet_addr(ip); sprintf(msgbuf,"##share %s", pathname);//拼接群里消息标志##all sendto(udp_socket,msgbuf,strlen(msgbuf),0,(struct sockaddr *)&dest_addr,sizeof(dest_addr)); recv_sharefile();//接收共享文件 }else if( n == 6) { //退出 //拼接退出通知协议 char quit[1024]={0}; sprintf(quit,"%s %s %s\n","##quit",argv[1],argv[2]); //设计退出通知协议 quit 姓名 IP //发送一个UDP 广播数据报 int ret = sendto(udp_socket,quit,strlen(quit),0,(struct sockaddr *)&dest_addr,sizeof(dest_addr)); if(ret < 0 ) { perror(""); } close(udp_socket); system("killall -9 main");//有时退出的时候进程会还在 得关了否则会出现udp绑定失败 return -1; } } return 0; }

//广播消息

int udp_broadcast(char const*argv[]) { //1.创建对象 udp_socket = socket(AF_INET, SOCK_DGRAM, 0); if(udp_socket 0) { if(strncmp(msg,"##loin",6)==0) //登陆通知 { sscanf(msg,"##loin %s %s %s %s %s",name_buf,ip_buf,sign_buf,path,share_file); printf("[%s]:%s上线了", name_buf, ip_buf); printf("个性签名:%s\n",sign_buf); //判断是否存在链表中 不存在则加入链表 if(FindNodes(head, name_buf) == NULL) { //加入链表中 Insert_Node_tail(head,udp_socket,name_buf,ip_buf,sign_buf,share_path,share_file); } //回发自己的信息 sendto(udp_socket,people,strlen(people),0,(struct sockaddr*)&dest_addr,len); continue; } if(strncmp(msg,"##reply",7)==0) //回发自己信息 让别人的好友列表有你在! {//##reply 小明 192.168.1.211 个性签名:city:揭阳Time:2022-09-0420:55:08weather:多云temp:32.00 ./ ||1.png sscanf(msg,"##reply %s %s 个性签名:%s %s %s",name_buf,ip_buf,sign_buf,path,share_file); //判断是否存在链表中 不存在则加入链表 if(FindNodes(head, name_buf) == NULL) { //加入链表中 Insert_Node_tail(head,udp_socket,name_buf,ip_buf,sign_buf,share_path,share_file); } continue; } if(strncmp(msg,"##quit",6)==0) //退出通知 { sscanf(msg,"##quit %s %s",name_buf,ip_buf); printf(" [%s] %s:下线了\n",ip_buf, name_buf); //判断是否存在链表中 存在则删除 if(FindNodes(head, name_buf) != NULL) { Remove_Node(head, name_buf); } continue; } if(strncmp(msg,"##share",7)==0) //接收共享文件请求 发送文件给好友 { sscanf(msg,"##share %s",share_path); printf("收到[%s]共享文件下载请求\n",ip); //tcp发送共享文件 send_file(share_path,ip,9898); continue; } if(strncmp(msg,"##msg",5) == 0) //接收好友私聊 { char strmsg[1024] = {0}; sscanf(msg,"##msg %s",strmsg); printf("[%s] %d: %s\n",ip, port, strmsg ); continue; } if(strncmp(msg,"##all",5) == 0) //接收群聊消息 { //##all[小明] 192.168.1.211: 66 char strname[128] = {0}; char msg1[1024] = {0}; sscanf(msg,"##all %s %s",strname,msg1); printf("群聊消息: %s[%s] : %s\n",strname,ip, msg1); } } } }

接收文件线程

//接收文件线程 void *recv_tcpfile(void *arg) { printf("服务器启动了。。\n"); while (1) { int ret =recv_file();//接收文件 端口设置6666 if(ret == -1) { break; } } }

捕捉ctrl+c信号  

void catch_sigint(int arg) { //退出 printf("触发键盘信号函数\n"); //拼接退出通知协议 char quit[1024]={0}; char name_buf[512] = {0}; char ip_buf[128] = {0}; sscanf(people,"##reply %s %s 个性签名:",name_buf,ip_buf); sprintf(quit,"%s %s %s\n","##quit",name_buf,ip_buf); //设计退出通知协议 quit 姓名 IP //发送一个UDP 广播数据报 int ret = sendto(udp_socket,quit,strlen(quit),0,(struct sockaddr *)&dest_addr,sizeof(dest_addr)); if(ret < 0 ) { perror(""); } close(udp_socket); system("killall -9 main");//有时退出的时候进程会还在 得关了否则会出现udp绑定失败 }

 tcp实现文件接收发送协议:

好友先绑定tcp服务器的端口,自己连接服务器 发送文件信息头(名字+大小)给好友,好友接收到头信息回发 可以发送了 创建文件并使用read接收文件 write写入文件,然后自己发送文件的内容write/send 好友接收并保存。 

//文件发送函数 int send_file(char *pathname, char *ip ,int port) { //发送文件名与大小给服务器 file 文件名 文件大小 int fd = open(pathname,O_RDWR); if(fd < 0) { perror(""); return -1; } //1.创建客户端通信socket int tcp_socket1 = socket(AF_INET, SOCK_STREAM, 0); if(tcp_socket1 < 0 ) { perror(""); } //2.设置服务器信息 struct sockaddr_in addr; addr.sin_family = AF_INET; //ipv4 addr.sin_port = htons(port);//端口为 8686 addr.sin_addr.s_addr = inet_addr(ip); //本地网卡地址 //链接服务器 int ret=connect(tcp_socket1,(struct sockaddr *)&addr,sizeof(addr)); if(ret < 0) { perror("链接失败\n"); return -1; }else{ printf("连接好友成功 准备发送文件\n"); } //获取文件大小 struct stat file_size; stat(pathname,&file_size); char file_msg[1024]={0}; //拼接协议 sprintf(file_msg,"file %s %ld",pathname,file_size.st_size); //发送给服务器 int a = write(tcp_socket1,file_msg,strlen(file_msg)); //等待服务器应答 char req[1024]={0}; read(tcp_socket1,req,1024); if(strcmp(req,"get_file_msg") == 0) //应答成功 { //发送文件内容 while (1) { //读取源文件数据 char data[4096]={0}; int size = read(fd,data,4096); if(size 0) //连接成功 { printf("开始接收………\n"); //接收文件名+文件大小 char file_msg[1024]; //file 文件名 文件大小 read(new_socet,file_msg,1024); //获取文件名和文件大小 char file_name[1024]; int file_size; if(strstr(file_msg,"file")) { sscanf(file_msg,"file %s %d",file_name,&file_size); }else{ printf("解析文件失败\n"); close(new_socet); //continue; } printf("对方发送的文件名 %s,文件大小 %d\n",file_name,file_size); //告诉发送端,已经得到了文件的信息 write(new_socet,"get_file_msg",strlen("get_file_msg")); //创建文件 int fd = open(file_name,O_RDWR|O_CREAT|O_TRUNC,0777); //下载大小 int down_size=0; //不断接收数据 while (1) { //读取网络数据 char data[4096]={0}; int size = read(new_socet,data,4096); down_size+=size; //写入本地文件 write(fd,data,size); //判断是否下载完毕 if(down_size >= file_size) { printf("下载完毕\n"); //告诉发送端已经下载完毕,可以断开链接 write(new_socet,"down_ok",strlen("down_ok")); close(fd); close(new_socet); break; }else{ printf("下载进度 %d %%\n",down_size*100/file_size); } } } }

链表操作:

struct node { char name[50]; char ip[50]; int socket; //描述符 char signature[1024];//个性签名 char pathname[512];//共享文件路径 char share_file[2048];//共享文件夹下的所有文件 struct node *next; }; 项目难点

第一个是udp/tcp协议的拼接使用,通过判断标志位来分别数据的不同和数据操作传输。

第二个是由于自己校园网 使用ucp比较繁琐 最终使用路由器解决 (开发板连接路由器,电脑连接路由器的网)但开发板有个缺点不支持udp组播。 

得设置绑定本地所有网卡 开发板或者虚拟机才能正常使用,广播发送接收数据。。。。 一开始的绑定自己的ip 

第三个是关闭的时候有时进程还在运行 得用killall -9 把进程关闭

心得体会 

此次网络编程项目运用的知识点比较广泛,基本覆盖了整个所学的知识,认识到udp/tcp/http等协议的实际编程运用,实现跨主机的数据交互。进一步提高自己的代码知识,项目代码编写更加规范。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有