linux实训项目——飞鸽(二)

编程入门 行业动态 更新时间:2024-10-11 17:26:54

linux<a href=https://www.elefans.com/category/jswz/34/1769369.html style=实训项目——飞鸽(二)"/>

linux实训项目——飞鸽(二)

本文主要为”飞鸽“的文件发送部分

文章目录

前言

一、实现过程及对比

1.1 实现过程

1.2 与例程对比

二、程序解析

2.1 发送文件

2.1.1 输入情况一

2.1.2 输入情况二

2.1.3 输入情况三

2.1.4 stat函数

2.1.5 数据报打包

2.2 接收文件

2.2.1 TCP连接部分

2.2.2 收写文件

2.3 添加文件

2.4 文件传输关键字

2.5 发送文件线程

2.6 当键入”ls“时展现当前文件目录下文件

总结


前言

  ipmsg全称:IP Messenger,中文名为“飞鸽传书”,是一款用C语言写的局域网聊天和文件传输工具。它是一个小巧方便的即时通信软件,它适合用于局域网内甚至广域网间进行实时通信和文档共享。特别是在局域网内传送文件/文件夹的效率很高。

  它具有很多优点,如数据通讯不需要建立服务器、直接在两台电脑间通信和数据传输,支持文件及文件目录的传输,安全快捷以及小巧方便等优异特点,因此很多公司都采用它作为部门、公司内部的IM即时通信工具。

  实训项目为在linux下用C语言写一个可以实现“飞鸽”功能的程序


一、实现过程及对比

1.1 实现过程

        发送文件:UDP讲请求发送文件的关键字发到指定ip的用户上,对方选择同意接收,主动发起TCP连接请求,进行连接。

        数据打包:读取发送文件的信息,存到特定字符串里进行发送。

        设置发送端缓冲区和接收端缓冲区,发送文件时,把待发送的文件放入缓冲区。接收到的字符串放入接收端缓冲区,读取后建立一同名文件,将字符写入文件。

        同时将文件信息存入信息表,可单独输出。

1.2 与例程对比

        给出例程文件是由链表连接存储,实现方式较为复杂,代码量较大,因此舍去。

二、程序解析

2.1 发送文件

假设输入有三种情况

情况一:输入 发送文件 选项,输入收件人,输入文件路径和文件名

情况二:输入 发送文件和收件人,输入文件路径和文件名

情况三:输入 发送文件、收件人、文件路径和文件名

2.1.1 输入情况一

//选择收件人
user_list();
printf("please select a user:");
scanf("%d",&uid);
getchar();

2.1.2 输入情况二

//选择文件
printf("input filename to %s[%s]:",usr->usr_name, usr->usr_ip);
fflush(stdout);
fgets(filename,sizeof(filename), stdin);
filename[strlen(filename)-1]='\0';

2.1.3 输入情况三

//读取文件名
strcpy(filename,argv[2]);

2.1.4 stat函数

int stat(const char *path, struct stat *buf);

stat函数自带结构体

struct stat {dev_t     st_dev;     /* 文件的设备编号 */ino_t     st_ino;     /* 索引结点编号 */mode_t    st_mode;    /* 文件类型和权限*/nlink_t   st_nlink;   /*硬链接数 */uid_t     st_uid;     /*用户ID*/gid_t     st_gid;     /* 组ID*/dev_t     st_rdev;    /* 设备类型(若此文件为设备文件,则为设备编号*/off_t      st_size;    /* 文件大小*/blksize_t   st_blksize; /*文件系统的I/O缓冲区大小*/blkcnt_t   st_blocks;  /* 块数 */time_t    st_atime;   /* 访问时间 */time_t    st_mtime;   /* 修改时间 */time_t    st_ctime;   /* 更改时间 */
}; 

2.1.5 数据报打包

sprintf(buf, "1:%d:%s:%s:%d:%c",t,user(),host(),IPMSG_SENDMSG|IPMSG_SENDCHECKOPT|IPMSG_FILEATTACHOPT,0);
sprintf(buf+strlen(buf)+1,"0:%s:%x:%x",filename,fstat.st_size,fstat.st_ctime); //打包文件信息
sendto(sockfd, buf, strlen(buf)+strlen(buf+strlen(buf)+1), 0, (struct sockaddr*)&addr, sizeof(addr));

2.2 接收文件

2.2.1 TCP连接部分

//TCP connection
if((sockfd = socket(AF_INET, SOCK_STREAM, 0))<0)
{perror("recv file socket");exit(1);
}
if(connect(sockfd, (struct sockaddr*)&(file.addr), sizeof(struct sockaddr))!=0)
{perror("connect");exit(1);
}

2.2.2 收写文件

if((fd=open(file.name,O_RDWR|O_CREAT,0666))<0)   //以只读或者追写的方式打开一个权限为666的同名文件
{perror("open");exit(1);
}
while(filesize!=0)  //filesize为接收文件的大小
{int len = recv(sockfd, buf,sizeof(buf),0);	//len为成功接收数据大小write(fd, buf, len);	//把buf中len长度的数据写入文件描述符fd所指的文档filesize -= len;
}

2.3 添加文件

temp[i++] = strtok(fileopt,":"); 	//按照:分割
while((temp[i++] = strtok(NULL,":"))!=NULL);sscanf(temp[2], "%x", &(file.size));	//从temp[2]中读出16进制数放到字符串里
sprintf(hex, "%x", atoi(packno));
strcpy(file.packno, hex);		//包编号
strcpy(file.fino, temp[0]);		//传进来的信息
strcpy(file.name, temp[1]);
file.addr = addr;

2.4 文件传输关键字

if(atoi(temp[4])&IPMSG_FILEATTACHOPT)	//传送文件选项
{printf("\rrecv file!\n");printf("MY_IPMSG>>");fflush(stdout);add_file(temp[1], fileopt, addr);
}

2.5 发送文件线程

if((cfd=accept(tcp_fd, (struct sockaddr*)&addr, &addrlen))<0)
{perror("accpet");exit(1);
}
recv(cfd, buf, sizeof(buf),0);
if((fd=open(sfile.name, O_RDONLY))<0)
{perror("open sendfile");exit(1);
}
while(sfile.size!=0)
{int len = read(fd, buf, sizeof(buf));send(cfd, buf, len,0);sfile.size -= len;
}

2.6 当键入”ls“时展现当前文件目录下文件

if(strcmp(temp[0], "ls")==0)
{pid_t pid=0;if((pid=fork())==0){execlp("ls","ls",NULL);}waitpid(pid,NULL,WUNTRACED);
}

总结

UI界面较为简陋,结果实现也有一定问题,期待后续改进。

更多推荐

linux实训项目——飞鸽(二)

本文发布于:2024-02-24 13:59:53,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1695529.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:实训   项目   linux   飞鸽

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!