版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
PAGE21目录1前言………………………71.1实习单位简介………………………71.2实习目的……………72实习内容…………………83实习总结…………………273.1实习中遇到的问题…………………273.2实习收获……………273.3实习建议……………283.4实习总结……………281前言1.1实习单位简介1.2实习目的(1)通过实习使学生对所要设计的课题有一个初步的了解,获得基本的感性认识,加深对课题的认识,学会理论联系实际,扩大知识面,引发设计思路,对设计任务有更明确更深刻的理解;(2)通过撰写实习报告和课题讨论,使学生学会综合应用所学知识,提高应用专业知识的能力,并为后续的毕业论文和毕业设计做好铺垫和准备;(3)通过实习能够开阔学生的视野,培养学生分析问题、解决问题的能力,进一步了解专业发展现状和前景,为以后的工作方向有更好的定位。2实习内容2.1文件操作2.1.1UNIX哲学之一:一切皆为文件Linux文件种类:1.普通文件2.目录文件3.链接文件4.设备文件2.1.2关于文件描述符文件描述符是一个非负整数,是一个索引值0STDIN_FILENO1STDOUT_FILENO2STDERR_FILENO包含在<unistd.h>文件描述符的范围是0~OPEN_MAXLinux下OPEN_MAX为10485762.1.3不带缓冲的文件I/O操作这次项目中将要用到的文件操作openclosereadwritelseek注:这些函数是ANSIC的组成部分,但是是POSIX的组成部分2.1.4关于出错处理由于对文件的操作由于某种原因,比如文件打开失败、文件读、写失败,这些出错会导致程序执行失败解决办法:加上出错处理,可以在出错时很明了的发现错误出在哪里常用函数:#include<errno.h>#include<stdio.h>voidperror(constchar*s);2.1.5不带缓冲的文件操作函数open#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>Intopen(constchar*pathname,intflags);Intopen(constchar*pathname,intflags,mode_tmode);返回值:成功返回新分配的文件描述符,出错返回-1并讴置errno2.1.6参数的含义pathname是要打开或创建的文件的名字。oflag参数可用于说明此函数的多个选择项。mode对于open函数而言,仅当创建新文件时才使用第三个参数。以下三个常数中必须指定一个,且仅允讲指定一个(这些常数定义在<fcntl.h>头文件中):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<unistd.h>Intclose(intfiledes);返回:若成功为0,若出错为-1当一个进程终止时,它所有的打开文件都由内核自动关闭。2.1.10read用read函数从打开文件中读数据#include<unistd.h>ssize_tread(intfeledes,void*buff,size_tnbytes);返回:读到的字节数,若已到文件尾为0,若出错为-1。如read成功,则返回读到的字节数。如已到达文件的尾端,则返回0。2.1.11write用write函数向打开文件写数据。#include<unistd.h>ssize_twrite(intfiledes,constvoid*buff,size_tnbytes);返回:若成功为已写的字节数,若出错为-1。其返回值通常不参数nbytes的值不同,否则表示出错。write出错的一个常见原因是:磁盘已写满,或者超过了对一个给定进程的文件长度限制。2.1.12lseek#include<sys/types.h>#include<unistd.h>off_tlseek(intfilesdes,off_toffset,intwhence);返回:若成功为新的文件位移,若出错为-1。对参数offset的解释不参数whence的值有关。若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<stdio.h>FILE*fopen(constchar*filename,constchar*mode)返回值:成功返回一个非空的FILE*指针,失败时返回NULL参数:mode可以是以下字符串中的一个(注意是字符串不是字符)2.1.15fopen“r”:只读,文件必须已存在“w”:只写,如果文件不存在则创建,如果文件已存在则把文件长度截断(Truncate)为0字节再重新写,也就是替换掉原来的的文件内容“a”:只能在文件末尾追加数据,如果文件不存在则创建“r+”:允许读和写,文件必须已存在“w+”:允许读和写,如果文件不存在则创建,如果文件已存在则把文件长度截断为0字节再重新写“a+”:允许读和追加数据,如果文件不存在则创建2.1.16fcloseIntfclose(FILE*fp);返回值:成功返回0,出错返回EOF并设置errno2.1.17fread/fwrite原型:#include<stdio.h>size_tfread/fwrite(void*ptr,size_tsize,size_tnmemb,FILE*stream)参数:size:读取/写入的记录大小nmemb:读取/写入的记录数返回值:成功返回实际读入或写入的记录数目失败返回EOF2.1.18fseek原型:#include<stdio.h>fseeek(FILE*stream,longintoffset,intwhence)其参数与前面lseek完全一样2.1.19fgets原型:#include<stdio.h>char*fgets(char*str,intn,FILEstream)说明:fgets函数从输入文件流stream里读取一个字符串。并把它读到的字符写到str指向的字符串里,直到:1、遇到换行符,应经传输了n-1个字符,或者达到文件尾。注意:它会把遇到的换行符也传递到接收字符串里,再在结尾加上一个表示结尾的空字节\0标准I/O的三种缓冲全缓冲如果缓冲区写满了就写回内核。常规文件通常是全缓冲的。行缓冲如果用户程序写的数据中有换行符就把这一行写回内核,或者如果缓冲区写满了就写回内核。标准输入和标准输出对应终端设备时通常是行缓冲的。不带缓冲用户程序每次调库函数做写操作都要通过系统调用写回内核。标准错误输出通常是无缓冲的,这样用户程序产生的错误信息可以尽快输出到设备。2.2Linux入门知识2.2.1Linux诞生Linux最初版本是1991年,芬兰赫尔辛基大学LinusTorvalds开发的;随后在网络上发布Linux0.0.2;到1993年底94年底,Linux1.0诞生;1993年Linux加入GNU并遵循公共版权许可证(GPL),从而为以后的快速发展创造了条件;1994Linux的第一个商业发行版Slackware问世;目前Linux的定位——服务器市场、桌面市场、嵌入式平台2.2.2GNU简介GNU(GNUIsNotUNIX)是自由软件基金会的一个项目,该项目的目标是开发一个自由的UNIX版本,这一UNIX版本称为HURD。GNU项目已经开发了许多高质量的编程工具,包括emacs编辑器、著名的GNUC和C++编译器(gcc和g++),这些编译器可以在任何计算机系统上运行。所有的GNU软件和派生工作均适用GNU通用公共许可证,即GPL(GeneralPublicLicense)。GPL允许软件作者拥有软件版权,但授予其他任何人以合法复制、发行和修改软件的权利。2.2.3什么是自由软件自由软件(freesoftware)中的free并不是指免费,而是指自由。它赋予使用者四种自由。自由之一:有使用软件的自由。自由之二:有研究该软件如何运作的自由,并且得以改写该软件来符合使用者自身的需求。取得该软件的源码是达成此目的前提。自由之三:有重新散布该软件的自由,所以每个人都可以有散布自由软件的自由。自由之四:有改善再利用该软件的自由,并且可以发表改写版供公众使用,如此一来,整个社群都可以受惠2.2.4目前linux的常见发行版本2.2.5Linux操作系统的架构2.2.6Linux下的常用命令命令的工作原理:用户在提示符下输入的名令经Shell(名令解释程序)解释后传给内核输入命令应注意:1、格式:命令【选项】【参数】2、区分大小写2.2.7Linux的文件命名规则由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~]#chmod664a.txt2.2.9Linux下开发工具——viVi是“Visualinterface”的简称Unix、Linux下的程序开发工具Unix、Linux下修改配置文件Vi可以执行输入、删除、查找、替换、块操作等众多文本操作Vi不是一个排版程序、它只是一个文本编辑程序Vi是全屏幕文本编辑程序,它没有菜单,只有命令现常用的为vi的升级版vim2.2.10Vi的安装使用Vim的安装:sudoapt-getinstallvimVim的使用:vi<文件名>——创建(如果没有创建)并进入文件例vihello.cvi编辑器有三种工作模式:命令行模式:刚进入文件即为此模式,此模式下可以移动鼠标、通过键盘输入一些命令完成查找、复制等功能,或进入底行模式、插入模式插入模式:在命令行模式下输入i或a进入(最常用为i),只有在命令行模式下才能字符输入,按【Esc】返回到命令行模式底行模式:在该模式下,用户可以将文件保存或退出。这一模式下的命令都以“:”开始2.2.11Linux编译器gcc及其使用编译如C、C++、ObjectC、Java、Fortran、Pasca等多种语言一个交叉平台编译器,适合在嵌入式领域的开发编译全称为GNUCompilerCollection,GNU项目中符合ANSIC标准的编译系统gcc可以使程序员灵活地控制编译过程。编译过程一般可以分为四个阶段,每个阶段分别调用不同的工具迚行处理使用格式:gcc【选项】源文件名连接:gcctest.o-otest一般情况下直接由源程序生成可执行文件:1、gcctest.c即可生成以a.out命名的可执行文件2、gcctest.c–otest(或其他名字)即生成具有自己命名的可执行文件执行:./可执行文件名2.2.12MakefileMakefile需要按照某种语法进行编写,其中说明了如何编译各个源文件并连接生成可执行文件,并定义了源文件之间的依赖关系。当修改了其中某个源文件时,如果其他源文件依赖于该文件,则也要重新编译所有依赖该文件的源文件。Makefile文件的建立:通常采用vimakefile,编辑完成后保存即生成makefile文件一个Makefile文件主要含有一系列的规则,每条规则包含以下内容:–一个目标(target),即make最终需要创建的文件,如可执行文件和目标文件;目标也可以是要执行的动作,如“clean”。–一个或多个依赖文件(dependency)列表,通常是编译目标文件所需要的其他文件。–一系列命今(command),是make执行的动作,通常是把指定的相关文件编译成目标文件的编译命令,每个命令占一行,且每个命令行的起始字符必须为TAB字符。Makefile的执行保存并退出makefile文件后,输入make命令如果要使用其他文件作为makefile,则可利用类似下面的make命令选项指定makefile文件:$make-fMakefile.debug2.2.13Make的工作过程首先make按顺序读取makefile中的规则然后检查该规则中的依赖文件与目标文件的时间戳哪个更新如果目标文件的时问戳比依赖文件还早,就按规则中定义的命令更新目标文件。如果该规则中的依赖文件又是其他规则中的目标文件,那么依照规则链不断执行这个过程,直到Makefile文件的结束,至少可以找到一个不是规则生成的最终依赖文件,获得此文件的时间戳然后从下到上依照规则链执行目标文件的时间戳比此文件时间戳旧的规则,直到最顶层的规则2.2.14Makefile的优点通过以上的分析过程,可以看到make的优点,因为.o目标文件依赖.c源文件,源码文件里一个简单改变都会造成那个文件被重新编译,并根据规则链依次由下到上执行编译过程,直到最终的可执行文件被重新连接。例如,当改变一个头文件的时候,由于所有的依赖关系都在Makefile里,因此不再需要记住依赖此头文件的所有源码文件,make可以自动的重新编译所有那些因依赖这个头文件而改变了的源码文件,如果需要,再进行重新连接2.3单向链表的实现2.3.1malloc和freemalloc是在堆上分配空间,并返回指向该段存储空间的地址#include<stdlib.h>void*malloc(size_tsize);voidfree(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链表节点的基本格式#defineMAX16#defineMAXLINE1024typedefstructclient*mylink;structclient{charuser[MAX];charcode[MAX];intfd;mylinknext;};2.3.5链表的插入2.4多进程编程2.4.1进程与程序程序(program)是存放在磁盘文件中的可执行文件。进程:程序的执行实例被称为进程(process)。进程ID:每个linux进程都一定有一个唯一的数字标识符,称为进程ID(processID)。进程ID总是一非负整数。2.4.2进程的三种状态运行状态(Running):占用处理机资源;处亍此状态的迚程的数目小于等于CPU的数目。在没有其他进程可以执行时(如所有进程都在阻塞状态),通常会自动执行系统的idle进程(相当于空操作)。就绪状态(Ready):进程已获得除处理机外的所需资源,等待分配处理机资源;只要分配CPU就可执行。可以按多个优先级来划分队列,如:时间片用完->低优,I/O完成->中优,页面调入完成->高优阻塞状态(Blocked):由于进程等待某种条件(如I/O操作或进程同步),在条件满足之前无法继续执行。该事件发生前即使把处理机分配给该进程,也无法运行。如:等待I/O操作的完成。2.4.3项目中使用多进程的原因本项目多进程只应用在了客户端原因是在客户端信息的发送和接收都是互相独立的,即并发执行,采用两个进程一个进程负责发送消息,一个进程负责接收消息,可以顺利的实现信息的发收本项目中服务器也可以才用多进程,即用多个进程分别处理所连接的各个用户的信息,但由于使用了select,所以省去了多进程2.4.4进程控制#include<sys/types.h>#include<unistd.h>pid_tfork(void);fork调用失败则返回-12.4.5fork用法一个父进程希望复制自己,使父、子进程同时执行不同的代码段。——网络服务器的经典代码一个进程要执行一个不同的程序。——这对shell是常见的情况。在这种情况下,子进程在从fork返回后立即调用exec函数。2.4.6fork发生了什么Fork产生的子进程是对父进程完整的复制但fork之后返回两个值,即一次调用,两个返回其中的一个返回值是子程序的id号,一个返回为0 》当返回值大于0,即为子进程ID时,父进程执行》当返回值等于0,子进程执行通过上述原理实现父进程、子进程执行不同的代码段2.4.7fork.c2.4.8代码分析父进程初始化。父进程调用fork,这是一个系统调用,因此进入内核。内核根据父进程复制出一个子进程,父进程和子进程的PCB信息相同,用户态代码和数据也相同。因此,子进程现在的状态看起来和父迚程一样,做完了初始化,刚调用了fork迚入内核,还没有从内核返回。现在有两个一模一样的进程看起来都调用了fork进入内核等待从内核返回(实际上fork只调用了一次),此外系统中还有很多别的进程也等待从内核返回。是父进程先返回还是子进程先返回,还是这两个进程都等待,先去调度执行别的进程,这都不一定,取决于内核的调度算法。如果某个时刻父进程被调度执行了,从内核返回后就从fork函数返回,保存在变量pid中的返回值是子进程的id,是一个大于0的整数,因此执下面的else分支,然后执行for循环,打印“Thisistheparent\n”三次之后终止。如果某个时刻子进程被调度执行了,从内核返回后就从fork函数返回,保存在变量pid中的返回值是0,因此执行下面的if(pid==0)分支,然后执行for循环,打印“Thisisthechild\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<stdlib.h>voidexit(intstatus);exit则先执行一些清除处理.然后进入内核清除操作包括调用执行各终止处理程序,关闭所有标准I/O流#include<unistd.h>void_exit(intstatus);_exit立即进入内核2.4.11异常终止信号终止信号是在软件层次上的对中断机制的一种模拟原理上,一个进程收到一个信号与处理器收到一个中断请求是一样的信号是异步的常用的用来终止进程的函数:#include<signal.h>#include<sys/types.h>intkill(pid_tpid,intsig)例kill(myid,SIGINT);2.5聊天室项目简介2.5.1项目说明基本架构:C/S架构何为C/S架构?即服务器(server)/客户端(client)结构2.5.2项目总体讲解基本功能:ClientA登陆聊天服务器前,需要注册自己的ID和密码注册成功后,ClientA就可以通过自己的ID和密码登陆聊天服务器多个ClientX可以同时登陆聊天服务器之后,与其他用户进行通讯聊天ClientA成功登陆后可以查看当前聊天室内其他在线用户ClientxClientA可以选择发消息给某个特定的ClientX,即”悄悄话”功能ClientA可以选择发消息全部的在线用户,即”群发消息”功能ClientA在退出时需要保存聊天记录Server端维护一个所有登陆用户的聊天会的记录文件,以便备查C语言开发的思路:C语言是一种面向过程的语言,即传统的结构化程序设计(StructuredProgrammingSP)方法在数据处理过程中,采用的是自顶向下、分而治之的方法,将整个程序按功能划分为几个可独立编程的子过程模块,每一子模块完成指定的子任务,最后,主过程通过调用各子过程完来成全部处理工作2.5.3根据架构划分2.5.4用户录入从标准输入接收用户的录入,提示用户输入相应信息可以使用函数fgets2.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位整数,在内存中存储的方式就不同.字节序分为小端字节序(LittleEndian)和大端字节序(BigEndian),Intel处理器大多数使用小端字节序,Motorola处理器大多数使用大端(BigEndian)字节序;2.6.2网络字节序TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节.为使网络程序具有可移植性,使同样的C代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换2.6.3网络字节序和主机字节序转换#include<arpa/inet.h>uint32_thtonl(uint32_thostlong);uint16_thtons(uint16_thostshort);uint32_tntohl(uint32_tnetlong);uint16_tntohs(uint16_tnetshort);这些函数名很好记,h表示host,n表示network,l表示32位长整数,s表示16位短整数。例如htonl表示将32位的长整数从主机字节序转换为网络字节序,例如将IP地址转换后准备发送。如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回,如果主机是大端字节序,这些函数不做转换,将参数原封不动地返回。2.6.4基于数据流的socket编程流程2.6.5socketIntsocket(intfamily,inttype,intprotocol);socket()打开一个网络通讯端口,如果成功的话,就像open()一样返回一个文件描述符,应用程序可以像读写文件一样用read/write在网络上收发数据,如果socket()调用出错则返回-1。对于IPv4,family参数指定为AF_INET即为遵循UNIX网络套接字。对于TCP协议,type参数指定为SOCK_STREAM,表示面向流的传输协议。(如果是UDP协议,则type参数指定为SOCK_DGRAM,表示面向数据报的传输协议。)protocol参数的介绍从略,指定为0即可。2.6.6bindIntbind(intsockfd,conststructsockaddr*myaddr,socklen_taddrlen);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,我们定义为97322.6.8listenintlisten(intsockfd,intbacklog);listen()成功返回0,失败返回-1。典型的服务器程序可以同时服务于多个客户端,当有客户端发起连接时,服务器调用的accept()返回并接受这个连接,如果有大量的客户端发起连接而服务器来不及处理,尚未accept的客户端就处于连接等待状态,listen()声明sockfd处于监听状态,并且最多允许有backlog个客户端处于连接待状态,如果接收到更多的连接请求就忽略。2.6.9select定义函数intselect(intn,fd_set*readfds,fd_set*writefds,fd_set*exceptfds,structtimeval*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(intfd,fd_set*set);用来设置描述词组set中相关fd的位FD_ZERO(fd_set*set);用来清除描述词组set的全部位参数timeout为结构timeval,用来设置select()的等待时间,其结构定义如下structtimeval{time_ttv_sec;time_ttv_usec;};如果参数timeout设为NULL则表示select()没有timeout。2.6.11返回值执行成功则返回文件描述符状态已改变的个数2.6.12acceptIntaccept(intsockfd,structsockaddr*cliaddr,socklen_t*addrlen);三方握手完成后,服务器调用accept()接受连接,如果服务器调用accept()时还没有客户端的连接请求,就阻塞等待直到有客户端连接上来。cliaddr是一个传出参数,accept()返回时传出客户端的地址和端口号。addrlen参数是一个传入传出参数(value-resultargument),传入的是调用者提供的缓冲区cliaddr的长度以避免缓冲区溢出问题,传出的是客户端地址结构体的实际长度(有可能没有占满调用者提供的缓冲区)。如果给cliaddr参数传NULL,表示不关心客户端的地址。2.6.13客户端程序Intconnect(intsockfd,conststructsockaddr*servaddr,socklen_taddrlen);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实习收获
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 房屋股权转让协议书
- 房屋装修易合同范本
- 房屋贴地板合同范本
- 房屋车租赁合同范本
- 房屋重建改造协议书
- 房屋预定协议协议书
- 房租买卖协议书模板
- 房租改造分隔协议书
- 房间租赁置换协议书
- 手机代售协议书范本
- 2025北京外国语大学财务专业技术岗位招聘笔试考试参考题库及答案解析
- 贵州辅警面试题目及答案
- 仓储物流月工作总结
- 2025年门球一级裁判试题及答案
- 慢性胸痛疾病诊断治疗指南
- 生产成本控制及核算数据表格模板
- 安全生产备案制度
- 魅力连云港课件
- 人教PEP版(2024)三年级上册英语Unit 2 Different families大单元整体教学设计
- 2025年时事政治热点题库道及参考答案
- 矿山修复申请书范文
评论
0/150
提交评论