Linux文件传输实习报告

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

学 生 实 习 报 告
实 习 名 称 毕 业 实 习 院 部 名 称 信息技术学院 专 业 计算机科学与技术 班 级 M08计算机科学与技术(嵌入式系统) 学 生 姓 名 学 号 实 习 地 点
指 导 教 师
实习起止时间: 2011 年7月 5 日至 2011年 7月29日
成绩
金陵科技学院教务处制
习项目名称:局域网文件传输系统实习学时: 25天
同组学生姓名:第三小组实习地点:无锡软通动力埃卡内基实习日期:2011年07月04月-07月29日成绩:
批改教师:批改时间:
实习报告
前言
无锡埃卡内基学院成立于2009年10月,由无锡市太湖新城科教产业园、美国卡内基梅隆大学软件教育培训中心(iCarnegie)以及国内领先的软件外包服务企业软通动力信息技术(集团)有限公司三方共同创办, 是经由江苏省无锡市教育局批准成立的高级IT人才培训学院。

软通动力埃卡内基学院凭借学院长期以来对金融、保险、电信和高科等行业的深厚积淀和庞大且丰富的技术知识资产,本着以客户为中心的办学方针,开创出一整套独有的人才培养方式,提供全方位多层次软件外包服务专业国际化人才解决方案。

无锡埃卡内基学院在人才输出渠道方面独具优势,目前已与多家国内外知名企业建立了战略合作关系,其中包括软通动力、爱立信、波音公司、花期银行,SalesForce等著名国内IT领头企业和跨国公司,成为其人才输出基地。

一、实习目的
1、掌握嵌入式微处理器的结构与原理
2、掌握一个嵌入式Linux操作系统
3、加强对Unix系统下的编程的各种知识点的整合与灵活运用;
4、掌握在Unix下socket编程,了解TCP、UDP等协议的使用;
5、熟悉嵌入式软件开发流程并至少做一个嵌入式软件项目。

二、实习时间
2011年07月05号~07月29号,具体安排如下表:
07月05号~07月14号1、职业素养培训
2、虚拟机下的Unix的安装
3、Unix基础;嵌入式技术发展现在及未来;
4、shell编程;
5、Unix系统知识、进程、线程、IPC、信号原理讲解、编程练习;
6、gtk编程;
7、网络基础、TCP/IP原理及编程;
8、数据库基础及SQL;
9、软件工程相关知识及UML.
07月15号各组项目的可行性和需求分析与项目开发计划07月16号项目概要设计
07月17号项目详细设计
07月18
号~07月
24号
项目代码编写
07月25
号~07月
27号
实现所有功能定义,交出测试报告
07月28号项目总结演示PPT
07月29号1、项目总结;
2、撰写实习报告。

三、实习地点
无锡软通动力埃卡内基培训基地教室305 四、实习单位和部门
实习单位:无锡软通动力科技有限公司
实习部门:无锡软通动力埃卡内基学院
五、实习内容
1、企业文化学习
(1)团队合作
通过各种游戏学习了在团队合作的过程中应该注意哪些方面,如何增强团队的合作能力。

(2)企业文化
通过ppt演示、找茬游戏认识了企业,了解了在企业当中应该注意的各种礼仪。

(3)职业规划
2、虚拟机下的linux的安装
目前PC机上的虚拟机软件有:VMWare、Virtual PC。

(1)VMWare的安装与配置
首先,要安装VMware 软件必须要有相应的安装程序,用户可下载程序vmware-workstation,然后就可以按步安装。

(2)在VMware中安装Linux,New—>Virtual Machine…->选择“custom”
下一步->下一步,出现的界面中选择安装路径,必须注意待安装盘有足够的空间。

因为后面安装的RedHat系统是桌面版本,它对内存还是有一定的要求,在机器内存较大的情况下,尽可能给RedHat多分配一些内存,此处分配的内存是256MB。

下面可以选择默认选择,最后单击”Close”,此时虚拟机已经建立起来了。

接下来光盘配置使用我们下载的RedHat是iso文件,单击OK按钮。

下面就可以启动安装RedHat系统了。

首先进行语言的选择,选择中文,并单击前进按钮。

接下来选择时区,此处选择上海时区,单击前进按钮。

在进行用户帐户和主机命名设置时,我用“zxy”作为登录名且同时作为这台计算机的名称。

安装向导的最后一步将用户安装过程中所做过的配置信息再次反馈给
用户,确认信息。

最后点击“安装”即可。

3、学习linux常用命令
1)cd【目录】: 切换到指定的目录,可以是相对路径或者是绝对路径。


对路径是以“ / ”开头,从目录的最顶层开始列出目录路
径。

相对路径不用“ / ”开头,只列出当前工作目录以下
的目录路径。

2)ls【选项】【文件目录列表】:显示指定工作目录中所包含的内容的指令
是ls,要说明的是ls命令列出文件的名字,而
不是文件的内容。

3)mkdir【选项】路径: “路径”可以是一系列,此时若路径中的目录不
存在,则系统自动创建那些不存在的目录。

4)Pwd:显示的是当前工作目录的绝对路径。

5)cp【选项】源文件目标文件或目标目录
6)mv【选项】文件列表目录
7)rm【选项】文件列表:可从文件系统中删除文件及整个目录。

8)cat【选项】文件列表:用来将几个文件的内容相连接,并显示到终端上。

9)Clear:清除屏幕上的信息。

10)kill进程号:删除执行中的进程。

11)tar [选项] 文件或者目录:文件打包解包。

12)ifconfig网络接口【选项】【地址】:配置网络接口的地址、网络掩码等。

13)gcc[选项]要编译的文件 [选项] [目标文件]:编译可执行文件。

4、配置Linux 的IP地址并查看连接
以“root”身份登录系统,打开终端窗口,在其中输入以下命令来配置IP 地址:ifconfig eth0 192.168.1.121
假设主机的IP地址为192.168.1.21。

在终端窗口中输入如下命令:ping 192.168.1.21。

如果能够ping通,则说明已经连接上。

在PC机上启动“开始”—>“运行”—>“cmd”,在出现的界面中输入:ping 192.168.1.121,如果能ping通则说明已经连接好。

5、安装VMWare Tools
具体使用如下命令:
1)cd /media/
2)cd cdrom
3)cp VMWare Tools_6.0.2_59824.tar.gz /tmp
4)cd tmp
5)tar xzvf VMWare Tools_6.0.0_59824.tar.gz
6)cd VMWare-tools-distrib/
7)./VMWare-install.pl
6、共享内存通信
1)共享内存通信概述
针对消息缓冲需要占用CPU进行消息复制的缺点,操作系统提供了一种进程间直接进行数据交换的通信方式——共享内存
2)共享内存通信原理
共享内存是由IPC为一个进程所创建并且出现在这个进程的地址空间中的一段特殊的地址序列。

其他的进程可以将同样的共享内存段关联到他们自己的地址空间中。

所有的进程都可以访问这段内存地址,就如同这段内存是由malloc所分配的。

共享内存原理示意图
3)共享内存通信的系统调用
shmget() 创建共享内存:
命令格式:
shmget( key, size, flag )
功能:
获得一个内部标识为shmid的共享存储区。

语句格式:
int shmid = int shmget ( key_t key, int size, int flag ); shmat() 映射共享内存
命令格式:
字符型共享内存:
shmat( int shmid, char *shmaddr, int msgflg, ulong *raddr );
数值型共享内存:
shmat( int shmid, int *shmaddr, int msgflg, ulong *raddr );
功能:
逻辑上将内部标识符为shmid的共享存储区附接到进程的虚拟地址空间shmaddr。

shmdt() 撤消映射
命令格式:
int shmdt(const void *shmaddr)
功能:
将一个共享存储区从指定进程的虚拟地址空间断开。

参数说明:
shmaddr——系统调用shmat()所返回的虚地址。

返回值:
正确返回:0
错误返回-1。

shmctl() 共享内存的控制
命令格式:
shmctl(int shmid, int cmd, struct shmid_ds *buf)
功能:
对与共享存储区关联的各种参数进行操作,从而对共享存储区进行控制包括删除共享存储区。

参数说明:
shmid——共享存储区的内部标识符,由shmget()调用返回;
Buf ——用户级数据结构地址,其结构类型与系统定义的shmid_ds一致,可以用 0。

4)共享内存通信的实现方法
A、发送进程
1. 使用系统调用函数shmget()创建或者获取指定key值的共享内存;
2. 使用系统调用函数shmat(),将该共享内存附接到自己的虚拟地址空间;
3.将需要发送的信息写入共享内存,方法有以下几种:
①.每条信息都以追加的方式写入,可以使用C语言提供的字符串追加函数
strcat(viraddr, buffer),该函数的功能是将buffer中的字符串追加
到由viraddr附接的共享存储区的尾部。

其中,viraddr是请求得到的
共享内存的地址,buffer是用户进程中请求的用来存放信息的字符缓冲
区。

②.每条信息都以覆盖的方式写入,可以使用strcpy(viraddr,buffer)函
数将buffer中的字符串复制到viraddr指向的共享内存中,则该共享
内存中就只有当前复制进来的信息,以前复制的信息被覆盖了。

③.共享内存定义为数值型变量,则可以将*viraddr作为数值型变量对其进
行操作。

例如将其赋值为0可以使用:*viradd=0。

④.共享内存定义为数值型数组,则可以将viraddr[i]作为下标变量使用。

例如将其赋值为0可以使用: viradd[i]=0。

4.使用系统调用函数shmdt(),断开共享内存。

B、接受进程
1. 用系统调用函数shmget();创建或者获取指定key值的共享内存;
2. 用系统调用函数shmat();将该共享内存附接到自己的程序空间;
3.将共享内存中的信息输出;或取出存放到其它数据块中;
4.使用系统调用函数shmdt();断开共享内存。

5.如果不再使用共享内存时,使用系统调用函数shmctl()将其撤消,格式为:shmctl(shmid,IPC_RMID,0);
5)共享内存通信应用实例分析
6)结论
1. 共享内存允许两个或多个进程共享一给定的存储区,因为数据不需要来回复
制,所以是最快的一种进程间通信机制。

共享内存可以通过mmap()映射普通文件(特殊情况下还可以采用匿名映射)机制实现,也可以通过系统V共享内存机制实现。

应用接口和原理很简单,内部机制复杂。

为了实现更安全通信,往往还与信号灯等同步机制共同使用。

2.共享内存涉及到了存储管理以及文件系统等方面的知识,深入理解其内部机
制有一定的难度,关键还要紧紧抓住内核使用的重要数据结构。

系统V共享内存是以文件的形式组织在特殊文件系统shm中的。

通过shmget可以创建或获得共享内存的标识符。

取得共享内存标识符后,要通过shmat将这个内存区映射到本进程的虚拟地址空间。

7、设计一个文件传输系统
1)项目组分工
2)项目函数
A、名字转成序号的散列算法
利用散列算法获得规律数字改变端口int get_int_from_name(char *name) {
char str[200] ;
int len, i ;
int value = 0 ;
unsigned int tmp ;
strcpy ( str, name ) ;
trim ( str) ; //字串开头和末尾的空格移除
len = strlen ( str ) ;
for (i=0; i<len; i++ )
{
tmp = str[i] ;
value = (value*11 + abs(str[i]) ) % 3999 ;
}
return value ;
}
B、列插入树
1.创建一个modle,定义了编号,文件名,接受者,进度,传送速度,文件大小,耗时,发送状态,并定义了其大小,实现函数如下,“XXX”代表下图呈现的“文件名”,“接受者”,“进度”,“传送速度”,“文件大小”,“耗时”,“发送状态”。

renderer = gtk_cell_renderer_text_new();
column=gtk_tree_view_column_new_with_attrib
utes(“XXX”,……);
gtk_tree_view_column_set_resizable();
gtk_tree_view_column_set_min_width();
gtk_tree_view_column_set_max_width();
gtk_tree_view_append_column(GTK_TREE_VIEW(tree), );
C、发送/接收端
程序通过调用socket函数,建立了监听连接的套接字,然后调用bind函数,将套接字与地址信息关联起来。

程序通过调用socket函数创建通信所需的套接字,然后,调用connect函数来连接服务器,在成功建立连接后,通过调用write函数向服务器发送指定的消息。

D、数据包
数据是网络和协议栈传输的实体和服务对象。

数据在传输时每通过一层就要在数据上加个包头,其中的数据供接收端同一层协议使用,而在接收端,每经过一层要把用过的包头去掉,这样来保证传输数据的格式完全一致。

我自己的任务:
E、消息队列
队列的基本函数
(1)初始化队列
int init_queue(QHead** queue_p)
(2)按序插入节点首部<尾部
int append(QHead* queue, QNode* node)
(3)从队列头部提取一个数据包
int serve(QHead* queue, PACKAGE** pack)
(4)提取指定的包(删除)
PACKAGE* retrive(QHead* queue, int pid)
(5)判断队列是否为空
int empty(const QHead* qhead)
(6)删除队列
int clean(QHead** queue_p)
消息队列代码:
#include <gtk/gtk.h>
#include <stdio.h>
#include <stdlib.h>
#include "Lequeue.h"
void display(QNode* node){
printf("%d ", LG_PACKAGE_DATA(node->pack)->pid);
}
/* 初始化一个队列,成功返回0,失败-1 */
int init_queue(QHead** queue_p)
{
*queue_p = (QHead *)g_malloc(sizeof(QHead)); /* 如果内存分配失败,g_malloc会返回错误信息 */
(*queue_p)->front = NULL;
(*queue_p)->rear = NULL;
return 0;
}
/* 创建一个新的QNode节点,并返回新节点的指针
time:pack包超时的时间
*/
QNode* queue_node(PACKAGE* pack, int time)
{
QNode* node = (QNode*)g_malloc(sizeof(QNode));
node->pack = pack;
node->time = time;
node->prev = NULL;
node->next = NULL;
return node;
}
/* 按序插入节点首部<尾部 */
int append(QHead* queue, QNode* node)
{
QNode* n = NULL;
if(queue == NULL){
printf("append:queue 参数错误\n");
return -1;
}
if(node == NULL){
printf("append:node 参数错误\n");
return -1;
}
if(queue->rear == NULL){ /* 队列为空 */
queue->rear = node;
queue->front = node;
}else if(LG_PACKAGE_DATA(queue->rear->pack)->pid < LG_PACKAGE_DATA(node->pack)->pid){/* 插入尾部 */
queue->rear->next = node;
node->prev = queue->rear;
queue->rear = node;
}else{
n = queue->rear;
while(n != NULL){/* 找到node的前驱节点 */
if(LG_PACKAGE_DATA(n->pack)->pid < LG_PACKAGE_DATA(node->pack)->pid)
break;
else
n = n->prev;
}
if(n == NULL){/* 插入队首 */
queue->front->prev = node;
node->next = queue->front;
queue->front = node;
}else{ /* 插入n节点后面 */
node->next = n->next;
n->next->prev = node;
n->next = node;
node->prev = n;
}
}
return 0;
}
/* 从队列头部提取一个数据包 */
int serve(QHead* queue, PACKAGE** pack) {
QNode* node;
if(queue == NULL){
printf("serve:参数错误\n");
return -1;
}
if(queue->front == NULL){
printf("serve:队列为空\n");
return -1;
}
node = queue->front;
queue->front = node->next;
if(queue->front != NULL) /* 判断node不为最后一个元素 */ queue->front->prev = NULL;
else
queue->rear = NULL;
*pack = node->pack;
g_free(node);
return 0;
}
/* 提取指定的包(删除) */
PACKAGE* retrive(QHead* queue, int pid)
{
if(queue == NULL){
printf("retrive:参数错误\n");
return NULL;
}
if(queue->front == NULL){
printf("retrive:队列为空\n");
return NULL;
}
QNode* node = queue->front; /* 迭代指针 */
PACKAGE* pack;
while(node != NULL){
if(LG_PACKAGE_DATA(node->pack)->pid == pid){
pack = node->pack;
break;
}else{
node = node->next;
}
};
if(node == NULL){
printf("retrive:没有ID为%d的包节点\n", pid);
Traversing(queue, display);
return NULL;
}
if((node->prev == NULL) && (node->next == NULL)){ /* node为唯一元素 */
queue->front = NULL;
queue->rear = NULL;
}else if(node->prev == NULL){ /* node为首元素 */
queue->front = node->next;
queue->front->prev = NULL;
}else if(node->next == NULL){ /* node为尾元素 */
queue->rear = node->prev;
queue->rear->next = NULL;
}else{/* node为中间元素 */
node->prev->next = node->next;
node->next->prev = node->prev;
}
g_free(node);
return pack;
}
/* 遍历队列 */
int Traversing(QHead* qhead, void process(QNode*))
{
if(qhead == NULL){
printf("Traversing:参数错误\n");
return -1;
}
if(qhead->front == NULL){
printf("Traversing:队列为空\n");
}
if(qhead->rear->next != NULL){
printf("Traversing:队列出错,尾部节点的next不为NULL\n");
}
if(qhead->front->prev != NULL){
printf("Traversing:队列出错,首部节点的next不为NULL\n");
}
QNode *pnode = qhead->front;
while(pnode != NULL){
process(pnode);
pnode = pnode->next;
}
printf("\n");
return 0;
}
/* 判断队列是否为空 */
int empty(const QHead* qhead)
{
if(qhead->front == NULL)
return 0;
else
return -1;
}
/* 删除队列 */
int clean(QHead** queue_p)
{
if((*queue_p) == NULL){
printf("clean: 参数错误\n");
return -1;
}
QNode* node;
QNode* p = (*queue_p)->front;
while(p != NULL){
node = p;
p = p->next;
g_free(node);
}
g_free(*queue_p);
*queue_p = NULL;
return 0;
}
/* 获取队列大小 */
int size(QHead* queue)
{
int size = 0;
QNode* node;
if(queue == NULL)
return 0;
node = queue->front;
while(node != NULL){
size++;
node = node->next;
}
return size;
}
F、数据插入列表
提取日志文件的TYPE、NAME、SIZE、USER、DATE、PATH信息插入列表。

主要代码如下:
key = lookup_keyword(buf);
switch(key){
case BEGIN:
break;
case LOG_ITEM_TYPE:
item->type = strdup(val);
break;
……
case END:
/* 提取迭代器 */
gtk_list_store_append(log_store,&iter);
gtk_list_store_set(log_store, &iter, LOG_TYPE_COLUMN, item->type,
……
-1);
3)项目计划
内容:
1.合理的人员分配
2.详细的书面计划
3.会议交流
4.合理利用资源
成果:
通过坚持上述计划内容,使得项目井然有序的进行,在有限的时间内最大限度地完成了项目的设计开发以及所有的后续整合和调试工作。

4)项目管理
会议:
成员:全组成员
时间:每天早晚
交流:
成员:全组成员
时间:随时随地
次数:不定
优化:
跟踪状况:每天记录遗留问题
交流状况:每天按时进行会议汇报交流工作
其他方法:
电子邮件、日程、数据库、报告等等
项目管理状况:
在项目前期提交了需求文档、概要设计文档以及详细设计文档,以及培养大家技能的各种小练习。

在详细设计文档中,由于欠缺经验,无法光凭自己完成函数流程图以及伪代码的设计,因此在项目实施过程中对此设计文档做了较大修改。

项目组在项目进行期间每天进行早晚例会,安排当天的任务、汇报项目完成进度、讨论项目开发过程中遇到的问题以及解决方案等。

5)项目总结
自身:
人是不断提升的,对待任何工作,应该是在最好的前提下不断学习。

我想我现在所拥有的知识是远远不够的,我会继续努力的。

团队:
分工协作,及时的发现提出问题,大家一起商讨解决方案,不断优化解决方法,提高工作效率。

6)重要教训
技术方面:
UDP是面向非连接的不可靠的协议,不对传输数据报进行检查,数据报可能被丢失、延误等等。

未设置添加用户重复IP报错机制,
未限制用户给自己传输文件
发送文件(>100M)时常常出现延迟现象。

计划方面:
需要留有时间,以作协调之用,使计划能更加完善
7)建议
技术性建议:
如果一定要使用UDP方式进行传输的话,为了提高传输的准确性,可以限制一下传输速度,在数据量小于65600字节的时候使用UDP是安全的
人性化建议:
适当增加提示窗口,如:发送成功、接受成功、添加用户成功等。

*用户是实例图:
*总流程图

结束
另存为..
接收成功
传输结束
开始
初始化
在线用户
选定用户
无目标用户
选择文件 发送方报错 接收方 确定发送
是 否
拒绝 接

六、实习总结
通过这次实习我真正的领会了linux的实际应用,有了对linux系统的深入理解。

实习的时候,老师重新为我们讲解了虚拟机的安装使用,及Linux的一些基础知识等,在后来的项目开发研究中,老师也帮我们一起商讨解决了很多技术上的的问题,我们体会到了理论和实践还是有相当大的差距的。

以前在学校里学习的书本上知识真正用到实践项目中有很大困难,根本无从下手,做一个项目需要相当多的储备知识,光凭学习课堂学到的那么点事完全不够的,
只有理论和实践的相结合,才能学会更多!
实习刚开始的时候,对很多软件的使用都很陌生,好多东西都是从头开始学习,尤其是对代码的编写,基础知识太差了,写不出自己所做项目的代码,最后都是借鉴了网上的资源,我在以后的学习中,要加强代码的编写,熟练掌握各种语言。

经过短短25天的学习,我也更加明白了在以后的工作及学习生活中,需要团队精神,有些事光靠自己一个人是完不成的,只有经过大家一起分工协作,共同协商解决问题,才能有更加完美的结果!人多力量才大。

也明白了以后工作时不能随便跟着自己感觉走,要注重公司形象和自己的形象。

职场礼仪是非常重要的,能体现整个团队的素养!
经过这次实习我懂得了个人的能力是团队的基础,只有不断的提高个人本事,才能为整个团队带来更大的帮助,有不懂的地方要及时向他人学习,虚心求教,不能不懂装懂,要时刻关注自己所在行业的最新状况,及时的吸取,只有学的更多,懂得更多,才能在以后的职场中有更大的立足之地,不然只会被淘汰的。

计算机行业更新发展的速度很快,想要适应,真的要付出很大的努力。

这次实习,我的团队非常和睦,大家都能互帮互助,共同学习。

这是大大出乎我的意料的!在学校的时候一直听说社会是黑暗的,社会上的人都很现实,都
是只忙着做自己的事,都会摆出一副“各人自扫门前雪,休管他人瓦上霜”的情态。

可是在这近一个月里,我根本就没感觉到这样的事情发现,我体会到的是我们是一个团队,我们是一个集体,个人的事就是集体的事,集体中的任何一员只要有任何问题都可以问任何人,在这样的集体里工作,我觉得是幸福的,是一种享受。

同时我能发挥我的所长,能充分利用自己的优势来开展自己的工作,这也正是我把理论与实际联系起来的大好机会,这还是我学习的最佳时机。

本次实习活动,我真的学到了很多,不仅学到了专业技术,更加锻炼了自己的能力,虽然时间很短暂,但是我也经过自己努力,为整个团队的项目制作做出了自己的贡献!。

相关文档
最新文档