文档库 最新最全的文档下载
当前位置:文档库 › 通信工程专业实习报告

通信工程专业实习报告

通信工程专业实习报告
通信工程专业实习报告

目录

1 前言 (7)

1.1实习单位简介 (7)

1.2实习目的 (7)

2 实习内容 (8)

3 实习总结 (27)

3.1实习中遇到的问题 (27)

3.2实习收获 (27)

3.3实习建议 (28)

3.4实习总结 (28)

1 前言

1.1实习单位简介...............................................................

1.2实习目的

(1)通过实习使学生对所要设计的课题有一个初步的了解,获得基本的感性认识,加深对课题的认识,学会理论联系实际,扩大知识面,引发设计思路,对设计任务有更明确更深刻的理解;

(2)通过撰写实习报告和课题讨论,使学生学会综合应用所学知识,提高应用专业知识的能力,并为后续的毕业论文和毕业设计做好铺垫和准备;

(3)通过实习能够开阔学生的视野,培养学生分析问题、解决问题的能力,进一步了解专业发展现状和前景,为以后的工作方向有更好的定位。

2 实习内容

2.1文件操作

2.1.1UNIX哲学之一:一切皆为文件

Linux文件种类:

1.普通文件

2.目录文件

3.链接文件

4.设备文件

2.1.2关于文件描述符

文件描述符是一个非负整数,是一个索引值

0 STDIN_FILENO

1 STDOUT_FILENO

2 STDERR_FILENO

包含在

文件描述符的范围是0 ~ OPEN_MAX

Linux 下OPEN_MAX为1048576

2.1.3不带缓冲的文件I/O操作

这次项目中将要用到的文件操作

open

close

read

write

lseek

注:这些函数是ANSI C的组成部分,但是是POSIX的组成部分

2.1.4关于出错处理

由于对文件的操作由于某种原因,比如文件打开失败、文件读、写失败,这些出错会导致程序执行失败

解决办法:

加上出错处理,可以在出错时很明了的发现错误出在哪里

常用函数:

#include

#include

void perror(const char *s);

2.1.5不带缓冲的文件操作函数

open

#include

#include

#include

Int open(const char *pathname, int flags);

Int open(const char *pathname, int flags, mode_t mode);

返回值:成功返回新分配的文件描述符,出错返回-1并讴置errno

2.1.6参数的含义

pathnameν是要打开或创建的文件的名字。

oflagν参数可用于说明此函数的多个选择项。

modeν对于open函数而言,仅当创建新文件时才使用第三个参数。

ν以下三个常数中必须指定一个,且仅允讲指定一个(这些常数定义在头文件中):

O_RDONLY 只读打开。

O_WRONLY 只写打开。

O_RDWR 读、写打开。

2.1.7可选

以下可选项可以同时指定0个或多个, 和必选项按位或来作为flags参数。

O_APPEND 每次写时都加到文件的尾端。

O_CREAT 若此文件丌存在则创建它。使用此选择项时,需同时说明第三个参数mode,用其说明该新文件的存取讲可权位。

O_EXCL 如果同时指定了O_CREAT,而文件已经存在,则出错。这可测试一个文件是否存在,如果不存在则创建此文件成为一个原子操作。

O_TRUNC 如果此文件存在,而且为只读或只写成功打开,则将其长度截短为0。

2.1.8第三个参数

第三个参数mode指定文件权限,可以用八进制数表示,比如0644表示-rw-r--r--

2.1.9close

可用close函数关闭一个打开文件:

#include

Int close (int filedes);

返回:若成功为0,若出错为-1

当一个进程终止时,它所有的打开文件都由内核自动关闭。

2.1.10read

用read函数从打开文件中读数据

#include

ssize_t read(int feledes, void *buff, size_t nbytes) ;

返回:读到的字节数,若已到文件尾为0,若出错为-1。

如read成功,则返回读到的字节数。如已到达文件的尾端,则返回0。

2.1.11write

用write函数向打开文件写数据。

#include

ssize_t write(int filedes, const void * buff, size_t nbytes) ;

返回:若成功为已写的字节数,若出错为-1。

其返回值通常不参数nbytes的值不同,否则表示出错。write出错的一个常见原因是:磁盘已写满,或者超过了对一个给定进程的文件长度限制。

2.1.12lseek

#include

#include

off_t lseek(int filesdes, off_t offset, int whence) ;

返回:若成功为新的文件位移,若出错为-1。

对参数offset 的解释不参数w h e n c e的值有关。

若whence是SEEK_SET,则将该文件的位移量设置为距文件开始处offset 个字节。

若whence是SEEK_CUR ,则将该文件的位移量设置为其当前值加offset,offset可为正或负。

若whence是SEEK_END ,则将该文件的位移量设置为文件长度加offset,offset可为正或负。

2.1.13标准I/O操作

标准i/o库及其头文件stdio.h为底层I/O系统调用提供了一个通用的接口,这个库已经成为ANSI标准C的一部分

在启动程序时,有三个文件流是自动打开的,他们是stdin ,stdout,stderr这三个文件分别代表着标准输入、标准输出、标准错误输出,与底层文件描述符0、1、2对应标准I/O库提供了大量的复杂函数

2.1.14fopen函数

函数原型

#include

FILE *fopen(const char *filename,const char *mode)

返回值:成功返回一个非空的FILE *指针,失败时返回NULL

参数:mode可以是以下字符串中的一个(注意是字符串不是字符)

2.1.15fopen

“r” :只读,文件必须已存在

“w”:只写,如果文件不存在则创建,如果文件已存在则把文件长度截断(Truncate)为0字节再重新写,也就是替换掉原来的的文件内容

“a”:只能在文件末尾追加数据,如果文件不存在则创建

“r+”:允许读和写,文件必须已存在

“w+”:允许读和写,如果文件不存在则创建,如果文件已存在则把文件长度截断为0字节再重新写

“a+”:允许读和追加数据,如果文件不存在则创建

2.1.16fclose

Int fclose(FILE *fp);

返回值:成功返回0,出错返回EOF并设置errno

2.1.17fread/fwrite

原型:

#include

size_t fread/fwrite(void *ptr,size_t size,size_t nmemb,FILE *stream)

参数:size:读取/写入的记录大小

nmemb:读取/写入的记录数

返回值:成功返回实际读入或写入的记录数目

失败返回 EOF

2.1.18fseek

原型:

#include

fseeek(FILE *stream,long int offset,int whence)

其参数与前面lseek 完全一样

2.1.19fgets

原型:#include

char *fgets(char *str,int n,FILE stream)

说明:fgets函数从输入文件流stream里读取一个字符串。并把它读到的字符写到str 指向的字符串里,直到:1、遇到换行符,应经传输了n-1个字符,或者达到文件尾。注意:它会把遇到的换行符也传递到接收字符串里,再在结尾加上一个表示结尾的空字节\0.

2.1.20标准I/O的三种缓冲

全缓冲

如果缓冲区写满了就写回内核。常规文件通常是全缓冲的。

行缓冲

如果用户程序写的数据中有换行符就把这一行写回内核,或者如果缓冲区写满了就写回内核。标准输入和标准输出对应终端设备时通常是行缓冲的。

不带缓冲

用户程序每次调库函数做写操作都要通过系统调用写回内核。标准错误输出通常是无缓冲的,这样用户程序产生的错误信息可以尽快输出到设备。

2.2 Linux入门知识

2.2.1 Linux诞生

Linux最初版本是1991年,芬兰赫尔辛基大学Linus Torvalds开发的;随后在网络上发布Linux0.0.2;到1993年底94年底,Linux 1.0诞生;1993年Linux加入GNU并遵循公共版权许可证(GPL),从而为以后的快速发展创造了条件;1994Linux 的第一个商业发行版 Slackware 问世;目前Linux 的定位——服务器市场、桌面市场、嵌入式平台

2.2.2 GNU简介

GNU(GNU Is Not UNIX)是自由软件基金会的一个项目,该项目的目标是开发一个自由的UNIX 版本,这一UNIX 版本称为HURD。GNU 项目已经开发了许多高质量的编程工具,包括emacs编辑器、著名的GNU C 和C++ 编译器(gcc和g++),这些编译器可以在任何计算机系统上运行。

所有的GNU 软件和派生工作均适用GNU 通用公共许可证,即GPL(General Public License)。GPL 允许软件作者拥有软件版权,但授予其他任何人以合法复制、发行和修改软件的权利。

2.2.3什么是自由软件

自由软件(free software)中的free并不是指免费,而是指自由。它赋予使用者四种自由。

自由之一:有使用软件的自由。

自由之二:有研究该软件如何运作的自由,并且得以改写该软件来符合使用者自身的需求。取得该软件的源码是达成此目的前提。

自由之三:有重新散布该软件的自由,所以每个人都可以有散布自由软件的自由。

自由之四:有改善再利用该软件的自由,并且可以发表改写版供公众使用,如此一来,整个社群都可以受惠

2.2.4目前linux的常见发行版本

2.2.5 Linux操作系统的架构

2.2.6 Linux下的常用命令

命令的工作原理:用户在提示符下输入的名令经Shell(名令解释程序)解释后传给内核

输入命令应注意:

1、格式:命令【选项】【参数】

2、区分大小写

2.2.7 Linux的文件命名规则

由Linux文件系统的规定,文件名和目录名可以包含以下字符:大写英文字母A-Z、小写英文字母a-z、数字0-9、“@”、“_”等。在文件名和目录中,不得包括的字符有:* ? > < / ; & ! [ ] | \‘“ ( ) { }。不得以”+“和”-“开头。

Linux中的文件名是大小写敏感的,也就是说,rainbow和Rainbow代表两个丌同的文件。一个以“.”打头的文件表明这个文件是隐藏文件(可以用ls-a 查看)。Linux系统中文件名的最大长度为255个字符。

2.2.8文件权限

文件的权限,分为三段,分别代表“所有者(u)”、“同组人(g)”、“其它人(o)”的读(r)、写(w)、执行(x) 的权限。

对普通文件而言,“r”代表可以阅读文件内容,“w”代表可以修改或删除文件内容,"x"代表可以将文件作为命令来执行(同时需要r权限)。

修改文件权限:命令——chmod(最常用)

例:[root@localhost ~]# chmod 664 a.txt

2.2.9 Linux下开发工具——vi

Viν是“Visual interface”的简称

Unixν、Linux下的程序开发工具

Unixν、Linux下修改配置文件

Viν可以执行输入、删除、查找、替换、块操作等众多文本操作

Viν不是一个排版程序、它只是一个文本编辑程序

Viν是全屏幕文本编辑程序,它没有菜单,只有命令

现常用的为vi的升级版vim

2.2.10 Vi的安装使用

Vim的安装: sudo apt-get install vim

Vim的使用:

vi <文件名>——创建(如果没有创建)并进入文件

例 vi hello.c

vi编辑器有三种工作模式:

命令行模式:刚进入文件即为此模式,此模式下可以移动鼠标、通过键盘输入一些命令完成查找、复制等功能,或进入底行模式、插入模式

插入模式:在命令行模式下输入i或a进入(最常用为 i),只有在命令行模式下才能字符输入,按【Esc】返回到命令行模式

底行模式:在该模式下,用户可以将文件保存或退出。这一模式下的命令都以“:”开始

2.2.11 Linux编译器gcc及其使用

编译如C、C++、Object C、Java、Fortran、Pasca等多种语言

一个交叉平台编译器, 适合在嵌入式领域的开发编译

全称为GNU Compiler Collection, GNU项目中符合 ANSI C标准的编译系统

gcc 可以使程序员灵活地控制编译过程。编译过程一般可以分为四个阶段,每个阶段分别调用不同的工具迚行处理

使用格式:gcc 【选项】源文件名

连接:gcc test.o -o test

一般情况下直接由源程序生成可执行文件:

1、gcc test.c 即可生成以a.out 命名的可执行文件

2、gcc test.c –o test (或其他名字)即生成具有自己命名的可执行文件

执行:./可执行文件名

2.2.12 Makefile

Makefile 需要按照某种语法进行编写,其中说明了如何编译各个源文件并连接生成可执行文件,并定义了源文件之间的依赖关系。当修改了其中某个源文件时,如果其他源文件依赖于该文件,则也要重新编译所有依赖该文件的源文件。

Makefile 文件的建立:

通常采用 vi makefile,编辑完成后保存即生成makefile文件

一个Makefile文件主要含有一系列的规则,每条规则包含以下内容:

–一个目标(target),即make最终需要创建的文件,如可执行文件和目标文件;目标也可以是要执行的动作,如“clean”。

–一个或多个依赖文件(dependency)列表,通常是编译目标文件所需要的其他文件。–一系列命今(command),是make执行的动作,通常是把指定的相关文件编译成目标文件的编译命令,每个命令占一行,且每个命令行的起始字符必须为TAB字符。Makefile的执行

保存并退出makefile文件后,输入make命令

如果要使用其他文件作为makefile,则可利用类似下面的make 命令选项指定makefile 文件:

$ make -f Makefile.debug

2.2.13 Make的工作过程

首先make按顺序读取makefile中的规则

然后检查该规则中的依赖文件与目标文件的时间戳哪个更新

如果目标文件的时问戳比依赖文件还早,就按规则中定义的命令更新目标文件。

如果该规则中的依赖文件又是其他规则中的目标文件,那么依照规则链不断执行这个过程,直到Makefile文件的结束,至少可以找到一个不是规则生成的最终依赖文件,获得此文件的时间戳

然后从下到上依照规则链执行目标文件的时间戳比此文件时间戳旧的规则,直到最顶层的规则

2.2.14 Makefile的优点

通过以上的分析过程,可以看到make的优点,因为.o目标文件依赖.c源文件,源码文件里一个简单改变都会造成那个文件被重新编译,并根据规则链依次由下到上执行编译过程,直到最终的可执行文件被重新连接。

例如,当改变一个头文件的时候,由于所有的依赖关系都在Makefile里,因此不再需要记住依赖此头文件的所有源码文件,make可以自动的重新编译所有那些因依赖这个头文件而改变了的源码文件,如果需要,再进行重新连接

2.3单向链表的实现

2.3.1 malloc和free

malloc是在堆上分配空间,并返回指向该段存储空间的地址

#include

void * malloc(size_tsize);

void free(void *pointer);

使用:

int* p;

p=malloc(100);

if(p==NULL)

{

}

2.3.2链表在物理内存上的存储

head指针是链表的头指针,指向第一个节点,每个节点的next指针域指向下一个节点,最后一个节点的next指针域为NULL,在图中用0表示。

机构图:

2.3.3链表的特点

每个链表有一个头指针,通过头指针可以找到第一个节点,每个节点都可以通过指针域找到它的后继,最后一个节点的指针域为NULL,表示没有后继。

数组在内存中是连续存放的,而链表在内存中的布局是丌规则的,我们知道访问某个数组元素b[n]时可以通过基地址+n×每个元素的字节数得到它地址,或者说数组支持随机访问,而链表是不支持随机访问的,只能通过前一个元素的指针域得知后一个元素的地址,因此只能从头指针开始顺序访问各节点。

2.3.4链表节点的基本格式

#define MAX 16

#define MAXLINE 1024

typedef struct client* mylink;

struct client {

char user[MAX];

char code[MAX];

int fd;

mylink next;

};

2.3.5链表的插入

2.4多进程编程

2.4.1进程与程序

程序(program)是存放在磁盘文件中的可执行文件。

进程: 程序的执行实例被称为进程(process)。

进程ID:每个linux进程都一定有一个唯一的数字标识符,称为进程ID(process ID)。进程ID总是一非负整数。

2.4.2进程的三种状态

运行状态(Running):占用处理机资源;处亍此状态的迚程的数目小于等于CPU的数目。在没有其他进程可以执行时(如所有进程都在阻塞状态),通常会自动执行系统的idle 进程(相当于空操作)。

就绪状态(Ready):进程已获得除处理机外的所需资源,等待分配处理机资源;只要分配CPU就可执行。可以按多个优先级来划分队列,如:时间片用完->低优,I/O完成->中优,页面调入完成->高优

阻塞状态(Blocked):由于进程等待某种条件(如I/O操作或进程同步),在条件满足之前无法继续执行。该事件发生前即使把处理机分配给该进程,也无法运行。如:等待I/O操作的完成。

2.4.3项目中使用多进程的原因

本项目多进程只应用在了客户端原因是在客户端信息的发送和接收都是互相独立的,即并发执行,采用两个进程一个进程负责发送消息,一个进程负责接收消息,可以顺利的实现信息的发收

本项目中服务器也可以才用多进程,即用多个进程分别处理所连接的各个用户的信息,但由于使用了select,所以省去了多进程

2.4.4进程控制

#include

#include

pid_t fork(void);

fork调用失败则返回-1

2.4.5 fork用法

一个父进程希望复制自己,使父、子进程同时执行不同的代码段。——网络服务器的经典代码

一个进程要执行一个不同的程序。——这对shell是常见的情况。在这种情况下,子进程在从fork返回后立即调用exec函数。

2.4.6 fork发生了什么

Fork产生的子进程是对父进程完整的复制

但fork之后返回两个值,即一次调用,两个返回

其中的一个返回值是子程序的id号,一个返回为0

》当返回值大于0,即为子进程ID时,父进程执行

》当返回值等于0,子进程执行

通过上述原理实现父进程、子进程执行不同的代码段

2.4.7 fork.c

2.4.8代码分析

父进程初始化。

父进程调用fork,这是一个系统调用,因此进入内核。内核根据父进程复制出一个子进程,父进程和子进程的PCB信息相同,用户态代码和数据也相同。因此,子进程现在的状态看起来和父迚程一样,做完了初始化,刚调用了fork迚入内核,还没有从内核返回。

现在有两个一模一样的进程看起来都调用了fork进入内核等待从内核返回(实际上fork只调用了一次),此外系统中还有很多别的进程也等待从内核返回。是父进程先返

回还是子进程先返回,还是这两个进程都等待,先去调度执行别的进程,这都不一定,取决于内核的调度算法。

如果某个时刻父进程被调度执行了,从内核返回后就从fork函数返回,保存在变量pid 中的返回值是子进程的id,是一个大于0的整数,因此执下面的else分支,然后执行for循环,打印“This is the parent\n”三次之后终止。

如果某个时刻子进程被调度执行了,从内核返回后就从fork函数返回,保存在变量pid 中的返回值是0,因此执行下面的if (pid== 0)分支,然后执行for循环,打印“This is the child\n”六次之后终止。fork调用把父进程的数据复制一份给子进程,但此后二者互不影响,在这个例子中,fork调用之后父进程和子进程的变量message和n被赋予不同的值,互不影响。

父进程每打印一条消息就睡眠1秒,这时内核调度别的进程执行,在1秒这样长的间隙里(对于计算机来说1秒很长了)子进程很有可能被调度到。同样地,子进程每打印一条消息就睡眠1秒,在这1秒期间父进程也很有可能被调度到。所以程序运行的结果基本上是父子进程交替打印,但这也不是一定的,取决于系统中其它进程的运行情况和内核的调度算法,如果系统中其它进程非常繁忙则有可能观察到不同的结果。另外,也可以把sleep(1);去掉看程序的运行结果如何

2.4.9终止进程

正常终止:

–从main返回

–调用exit

–调用_exit

异常终止

–调用abort

–由一个信号终止

2.4.10正常终止

exit和_exit函数用于正常终止一个程序

#include

void exit(int status) ;

exit则先执行一些清除处理.然后进入内核

清除操作包括调用执行各终止处理程序,关闭所有标准I / O流

#include

void _exit (int status) ;

_exit立即进入内核

2.4.11异常终止

信号终止

信号是在软件层次上的对中断机制的一种模拟

原理上,一个进程收到一个信号与处理器收到一个中断请求是一样的

信号是异步的

常用的用来终止进程的函数:

#include

#include

int kill(pid_t pid,int sig) 例 kill(myid,SIGINT);

2.5聊天室项目简介

2.5.1项目说明

基本架构:C/S架构

何为C/S架构?

即服务器(server)/客户端(client)结构

2.5.2项目总体讲解

基本功能:

Client A 登陆聊天服务器前,需要注册自己的ID和密码

注册成功后,Client A 就可以通过自己的ID和密码登陆聊天服务器

多个Client X 可以同时登陆聊天服务器之后,与其他用户进行通讯聊天

Client A成功登陆后可以查看当前聊天室内其他在线用户Client x

Client A可以选择发消息给某个特定的Client X,即”悄悄话”功能

Client A 可以选择发消息全部的在线用户,即”群发消息”功能

Client A 在退出时需要保存聊天记录

Server端维护一个所有登陆用户的聊天会的记录文件,以便备查

C语言开发的思路:

C语言是一种面向过程的语言,即传统的结构化程序设计(Structured Programming---SP)方法

在数据处理过程中,采用的是自顶向下、分而治之的方法,将整个程序按功能划分为几个可独立编程的子过程模块,每一子模块完成指定的子任务,最后,主过程通过调用各子过程完来成全部处理工作

2.5.3根据架构划分

2.5.4用户录入

从标准输入接收用户的录入,提示用户输入相应信息可以使用函数fgets

2.5.5信息打包

确立自己的通信协议,即每次传递的信息包含哪些

这里的协议可以是一个结构体,打包即将用户录入添加到结构体中

2.5.6信息发送、接收

读、写套接字

注:在读写时注意类型转换

2.5.7信息显示

取出包内信息,并输出

2.5.8保存消息

将消息写入到定好的文件中

2.5.9传递消息

采用TCP/ip协议,采用网络编程实现客户端与服务器的通信

2.5.10服务器解析消息

服务器收到数据后,将数据解析,根据不同的模式执行不同的操作处理包括:链表操作、信息转发、信息回应等

2.5.11实习目标

了解linux下C开发平台

学会使用gnu开发工具

了解C语言开发流程,提高c语言编程能力

对所做项目有一定了解,熟悉本项目的开发思路及所用知识,培养软件开发兴趣

2.6网络编程

2.6.1字节序

由于丌同的计算机系统采用不同的字节序存储数据,同样一个4字节的32位整数,在内存中存储的方式就不同. 字节序分为小端字节序(Little Endian)和大端字节序(Big Endian), Intel处理器大多数使用小端字节序, Motorola处理器大多数使用大端(Big Endian)字节序;

2.6.2网络字节序

TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节.

为使网络程序具有可移植性,使同样的C代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换

2.6.3网络字节序和主机字节序转换

#include

uint32_t htonl(uint32_t hostlong);

uint16_t htons(uint16_t hostshort);

uint32_t ntohl(uint32_t netlong);

uint16_t ntohs(uint16_t netshort);

这些函数名很好记,h表示host,n表示network,l表示32位长整数,s表示16位短整数。例如htonl表示将32位的长整数从主机字节序转换为网络字节序,例如将IP地址转换后准备发送。如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回,如果主机是大端字节序,这些函数不做转换,将参数原封不动地返回。

2.6.4基于数据流的socket编程流程

2.6.5socket

Int socket(int family, int type, int protocol);

socket()打开一个网络通讯端口,如果成功的话,就像open()一样返回一个文件描述符,应用程序可以像读写文件一样用read/write在网络上收发数据,如果socket()调用出错则返回-1。

对于IPv4,family参数指定为AF_INET即为遵循UNIX网络套接字。

对于TCP协议,type参数指定为SOCK_STREAM,表示面向流的传输协议。(如果是UDP 协议,则type参数指定为SOCK_DGRAM,表示面向数据报的传输协议。)

protocol参数的介绍从略,指定为0即可。

2.6.6bind

Int bind(int sockfd, const struct sockaddr* myaddr, socklen_t addrlen); bind()成功返回0,失败返回-1。

服务器程序所监听的网络地址和端口号通常是固定不变的,客户端程序得知服务器程序的地址和端口号后就可以向服务器发起连接,因此服务器需要调用bind绑定一个固定的网络地址和端口号。

bind()的作用是将参数sockfd和myaddr绑定在一起,使sockfd这个用于网络通

讯的文件描述符监听myaddr所描述的地址和端口号。

2.6.7sockaddr 初始化

bzero(&servaddr, sizeof(servaddr));

servaddr.sin_family= AF_INET;

servaddr.sin_addr.s_addr= htonl(INADDR_ANY); servaddr.sin_port= htons(SERV_PORT);

首先将整个结构体清零,然后设置地址类型为AF_INET,网络地址为INADDR_ANY,这个宏表示本地的任意IP地址,因为服务器可能有多个网卡,每个网卡也可能绑定多个IP 地址,这样设置可以在所有的IP地址上监听,直到不某个客户端建立了连接时才确定下来到底用哪个IP地址,端口号为SERV_PORT,我们定义为9732

2.6.8listen

intlisten(intsockfd, intbacklog);

listen()成功返回0,失败返回-1。

典型的服务器程序可以同时服务于多个客户端,当有客户端发起连接时,服务器调用的accept()返回并接受这个连接,如果有大量的客户端发起连接而服务器来不及处理,尚未accept的客户端就处于连接等待状态,listen()声明sockfd处于监听状态,并且最多允许有backlog个客户端处于连接待状态,如果接收到更多的连接请求就忽略。

2.6.9select

定义函数int select(int n,fd_set* readfds,fd_set* writefds,fd_set* exceptfds,struct timeval* timeout);函数说明select()用来等待文件描述符状态的改变。

参数n代表最大的文件描述符加1,参数readfds、writefds和exceptfds称为描述符组,是用来回传该描述符的读,写或例外的状况。

2.6.10Select的操作

select底下的宏提供了处理这三种描述词组的方式:

FD_CLR(intfd,fd_set* set);用来清除描述词组set中相关fd的位

FD_ISSET(intfd,fd_set*set);用来测试描述词组set中相关fd的位是否为真

FD_SET(int fd,fd_set*set);用来设置描述词组set中相关fd的位

FD_ZERO(fd_set*set);用来清除描述词组set的全部位参数 timeout为结构timeval,用来设置select()的等待时间,其结构定义如下struct timeval{time_ttv_sec;time_ttv_usec;};如果参数timeout设为NULL则表示select ()没有timeout。

2.6.11返回值

执行成功则返回文件描述符状态已改变的个数

2.6.12accept

Int accept(intsockfd, struct sockaddr*cliaddr, socklen_t *addrlen);

三方握手完成后,服务器调用accept()接受连接,如果服务器调用accept()时还没有客户端的连接请求,就阻塞等待直到有客户端连接上来。

cliaddr是一个传出参数,accept()返回时传出客户端的地址和端口号。

νaddrlen参数是一个传入传出参数(value-result argument),传入的是调用者提供的缓冲区cliaddr的长度以避免缓冲区溢出问题,传出的是客户端地址结构体的实际长度(有可能没有占满调用者提供的缓冲区)。

ν如果给cliaddr参数传NULL,表示不关心客户端的地址。

2.6.13客户端程序

Int connect(int sockfd, const structsockaddr*servaddr, socklen_t addrlen); connect()成功返回0,出错返回-1。

客户端需要调用connect()连接服务器,connect和bind的参数形式一致,区别在于bind 的参数是自己的地址,而connect的参数是对方的地址。

3 实习总结

3.1实习中遇到的问题

Q1:什么是多文件处理,如何操作?

这个问题是我此次实习时一上来就遇到的问题,因为老师讲过,我也遇到过,当我们写程序时,若只在一个文件中写,写的代码可能会有几百上千行,维护起来特别麻烦。所以要用到多文件管理,可是,如何调用文件,如何定义,在主函数中如何声明,这是我所不知道的,我也是问了老师两遍,才弄清楚。多文件,要在主函数中声明你要用的函数,并在分文件中定义。其实就这么简单,必要的头文件如“stdafx.h”一定要包含进去就可以了。

Q2:怎么读入文件,怎么输出到文件?

这个是我自己看书解决的,我的思路很明确,把文件当做数据库,我输入的数据写到里面,回来我再调用,每个函数都会把文件中的内容读入到结构体数组中,然后我在查找,修改,删除,排序等,最后完成操作后,若有变动,则再次写入到文件中,这样下次再使用时,就是用户改过的内容。这里比较重要的是要知道文件中有多少条记录,用到了feof函数以及fopen,fread,fwrite,fclose函数。feof是查找文件否到了末尾,其余的就不用说了。

Q3:“容错”处理?

这个是比较让人头疼的事,你得想到各种情况,比如,你让用户输入数字来选择相应功能,但是用户输入了字母,这个时候就要提示用户输入错误,并再次出现菜单,这就需要循环语句,但是我遇到了死循环,就是因为每次用户输入一个选项后,会有敲下回车,这个回车会在文件缓冲区中,下一次scanf()语句执行时,会直接得到这个回车,造成死循环。因此要写一条语句“吃掉”这个回车。

3.2实习收获

这次实习,除了让我对软件开发的基本知识有了一定了解,并且能进行基本操作外,我觉得自己在其他方面的收获也是挺大的.作为一名一直生活在单纯的大学校园的我,这次的实习无疑成为了我踏入社会前的一个平台,为我今后踏入社会奠定了基础.

首先,我觉得在校学习和毕业实习的最大一个不同就是必须要有很强的责任心.在毕业实习时,我们必须要有强烈的责任感,要对自己工作负责,要对自己负责.如果没有完成当天应该完成的学习内容,那就必须得自己找时间自学;如果不小心出现了错误,也必须及时纠正。

其次,我觉得每个人都必须要坚守自己的职业道德和努力提高自己的职业素养,正所谓做一行就要懂一行的行规.在这一点上我在实习时深有体会.比如,在学习理论知识时,如果有不懂的地方必须提出来并且尽快的找出解决的方法,否则将会对自己的实习有一定的影响。所以对于我来说,实习态度问题尤为重要.

最后,我觉得毕业实习以后,学历并不显得最重要,主要看的是个人的工作能力和交际能力.任何工作,做得时间久了是谁都会做的,在实际工作中动手能力更重要.

因此,我体会到,如果将我们在大学里所学的知识与更多的实践结合在一起,用实践来检验真理,使一个本科生具备较强的处理基本事务的能力与比较系统的专业知识,这才是我们实习的真正目的.

很感谢实习单位给我这个这么好的实习机会,让我学习很多、成长很多、收获很多。

3.3实习建议

(1)注重理论联系实际,多动手实践操作

(2)注意与同组人员配合,锻炼团队协作能力

(3)总结学习方法,找到合适自己的方法,提高学习效率

(4)大胆操作,勇于创新,活跃自己的思维

3.4实习总结

实习期间,对于任何知识的学习一贯谦虚谨慎、认真学习。如今的我通过此次实习了解到很多的软件开发知识。我想这除了有较强的适应能力和积极向上的心态以外,更重要的是得益于实习老师的悉心指导。

实习生活,给我仅是初步的经验积累,对于迈向社会是远远不够的。“吃的苦中苦,方为人上人”,我要恪守吃苦精神。因此,在今后,我会继续努力拼搏,抓住每一个机遇,迎接每一个挑战,相信自己一定会演绎出精彩的一幕。

刚进实习的时候,很茫然,不知道要做些什么,我们实习小组一共有7个人,所以不是每天都很忙,很多时候我们都是学习讨论所学习的知识,一以讨论就是一整天,直到一天的实习结束,后来才慢慢走入正轨,自己动手实现一些程序。

通过此次实习,让我学到了很多课堂上更本学不到的东西,仿佛自己一下子成熟了,懂得了做人做事的道理,也懂得了学习的意义,时间的宝贵,人生的真谛。明白人世间一生不可能都是一帆风顺的,只要勇敢去面对人生中的每个驿站!这让我清楚地感到了自己肩上的重任,看清了自己的人生方向,也让我认识到了文秘工作应支持仔细认真的工作态度,要有一种平和的心态和不耻下问的精神,不管遇到什么事都要总代表地去思考,多听别人的建议,不要太过急燥,要对自己所做事去负责,不要轻易的去承诺,承诺了就要努力去兑现。单位也培养了我的实际动手能力,增加了实际的操作经验,对实际的财务工作的有了一个新的开始,更好地为我们今后的工作积累经验。我知道工作是一项热情的事业,并且要持之以恒的品质精神和吃苦耐劳的品质。我觉得重要的是在这段实习期间里,我第一次真正的融入了社会,在实践中了解社会掌握了一些与人交往的技能,也打开了视野,增长了见识,为我们以后进一步走向社会打下坚实的基础

实习期间,我从末出现无故缺勤。我勤奋好学.谦虚谨慎,认真听取老师的指导,对于别人提出的建议虚心听取并能够仔细观察、切身体验、独立思考、综合分析,并努力学到把学样学到的知道应用到实际工作中,尽力做到理论和实际相结合的最佳状态,培养了我执着的敬业精神和勤奋踏实的工作作风。也培养了我的耐心和素质。并始终坚持一条原则:要么不做,要做就要做最好。

相关文档