第9章 网络通信编程
- 格式:pdf
- 大小:710.67 KB
- 文档页数:86
c语言网络通信课程设计一、教学目标本课程旨在让学生掌握C语言在网络通信领域的基本原理和应用技能。
通过本课程的学习,学生将能够:1.知识目标:理解网络通信的基本概念、原理和技术;掌握C语言在网络通信编程中的基本语法和常用函数。
2.技能目标:能够运用C语言进行简单的网络通信程序设计;具备分析、解决网络通信问题的能力。
3.情感态度价值观目标:培养学生对网络通信技术的兴趣和好奇心,提高学生运用C语言进行创新实践的意识和能力。
二、教学内容本课程的教学内容主要包括以下几个部分:1.网络通信基本概念:计算机网络、网络协议、网络结构等。
2.C语言网络通信编程基础:C语言语法、数据类型、运算符、函数等。
3.常用网络通信函数和协议:socket编程、TCP/IP协议、UDP协议等。
4.网络通信程序设计实例:文件传输、聊天室、网络管理等。
5.实验环节:通过实际操作,巩固所学知识,提高实际编程能力。
三、教学方法本课程采用多种教学方法,以激发学生的学习兴趣和主动性:1.讲授法:讲解基本概念、原理和技术,确保学生掌握基础知识。
2.讨论法:学生分组讨论,培养学生的思考和分析能力。
3.案例分析法:分析实际案例,让学生了解网络通信在实际应用中的原理和技巧。
4.实验法:通过实际操作,让学生亲手编写网络通信程序,提高实践能力。
四、教学资源为实现教学目标,我们将提供以下教学资源:1.教材:《C语言网络通信教程》。
2.参考书:提供相关领域的经典教材和论文,以拓展学生的知识视野。
3.多媒体资料:制作课件、教学视频等,丰富教学手段,提高教学质量。
4.实验设备:提供计算机、网络设备等,确保学生能够进行实际操作。
五、教学评估本课程的教学评估将采用多元化方式,全面、客观地评价学生的学习成果。
评估方式包括:1.平时表现:考察学生在课堂上的参与度、提问回答、小组讨论等,占总评的30%。
2.作业:布置课后编程作业,让学生巩固所学知识,占总评的20%。
3.考试:进行期中和期末考试,测试学生对课程知识的掌握程度,占总评的50%。
Windows⽹络编程复习重点⽬录第⼀章⽹络应⽤程序设计基础 (3)分布式⽹络应⽤程序的特点及分类 (3)⾯向应⽤的⽹络编程⽅法(3点) (3)基于TCP/IP的⽹络编程⽅法 (3)⾯向原始帧的⽹络编程⽅法(4种) (4)第⼆章⽹络程序通信模型 (4)常见的⽹络编程通信模型 (4)客户端、服务器的⼯作过程 (4)P2P模型的特点及其⽹络的拓扑结构 (5)第三章⽹络数据的内容与形态 (6)⽹络字节顺序与主机字节顺序 (6)⽹络字节顺序与主机字节顺序转换的函数 (6)⽹络数据传输形态 (6)字符编码 (7)数据校验 (7)第四章软件协议接⼝ (7)协议软件接⼝的位置与功能 (7)WinSock DLL的初始化与释放 (8)WinSock的地址描述 (9)套接字选项和IO控制命令 (9)处理WinSock的错误 (9)第五章流式套按字编程 (9)流式套接字通信的特点 (9)流式套接字的适⽤场景 (10)基本函数 (10)流式套接字编程的⼀般过程 (12)正确处理流数据的接收 (13)接收定长和变长数据 (13)流式套接字的编程实例 (13)第六章数据报套接字编程 (21)数据报套接字数据通信的特点 (21)数据报套接字的适⽤场景 (21)数据报套接字的编程的⼀般过程 (21)数据报套接字的常⽤函数 (22)数据报套接字的编程实例 (22)第七章原始套接字编程 (27)原始套接字的特点 (27)原始套接字的适⽤场景 (28)原始套按字的编程的⼀般过程 (28)原始套接字的编程实例 (28)第⼋章⽹络通信中的IO操作 (37)套接字的常见IO模式 (37)同步、异步、阻塞、⾮阻塞的概念及区别 (37)阻塞IO模型的⼯作原理与特点 (38)⾮阻塞IO模型的⼯作原理与特点 (38)IO复⽤模型的⼯作原理与特点(选择模型) (38)异步IO复⽤模型的⼯作原理与特点(WSAAsynsSelect) (38)完成端⼝模型的⼯作原理与特点(异步) (39)第九章WinPcap编程 (39)Wpcap.dll的⼯作流程 (39)Wpcap.dll的编程实例 (40)Packet.dll的⼯作流程 (45)Packet.dll编程实例 (45)第⼀章⽹络应⽤程序设计基础分布式⽹络应⽤程序的特点及分类1、特点:3点A)分布式⽹络应⽤程序将整个应⽤程序的处理分成⼏个部分,分别在不同的机器上运⾏,这⾥的“分布”包含两层含义:地理上的分布和数据处理的分布。
手机作为一种通讯终端(MMS),伴随着网络的升级而不断的升级换代。
1995年1G问世,手机只能进行基本的语音通讯,1996-1997年2G(GSM,CDMA)及其后的GPRS,EDGE等技术的快速发展,手机开始逐渐增加了数据服务功能。
2009年开始,3G在全世界开始大规模布置以及苹果创造性开发新型苹果手机。
手机慢慢的变成互联网的终端,从而带动了一个新的时代--移动互联网时代。
因此现代手机通常都支持这些常用网络设备,如WIFI,NFC,蓝牙等。
Android是由互联网巨头Google带头开发的,因此对网络功能的支持是必不可少的。
Google 的应用层采用的是Java语言。
所以JAVA支持的网络编程方式Android都支持,同时Google 还引入了Apache 的HTTP扩展包。
另外,针对WIFI,NFC,分别提供的单独的开发API.表1展示了Android SDK中的一些与网络有关的API包名表1. Android SDK 网络包包描述 API Level 提供与联网有关的类,包括流和数据包(datagram)sockets、Internet 协议和常见HTTP 处理。
该包是一个多功能网络资源。
有经验的Java 开发人员可以立即使用这个熟悉的包创建应用程序。
1java.io 虽然没有提供显式的联网功能,但是仍然非常重要。
该包中的类由其他Java 包中提供的socket 和连接使用。
它们还用于与本地文件(在与网络进行交互时会经常出现)的交互 1java.nio 包含表示特定数据类型的缓冲区的类。
适合用于两个基于Java 语言的端点之间的通信。
1org.apache.* 表示许多为HTTP 通信提供精确控制和功能的包。
可以将Apache 视为流行的开源Web 服务器。
1 除核心.* 类以外,包含额外的网络访问socket。
该包包括URI 类,后者频繁用于Android 应用程序开发,而不仅仅是传统的联网方面。
第9章网络通信编程实验目的加深对网络编程原理的理解深入了解客户/服务器网络编程的执行流程 学会使用套接字建立客户/服务器程序主要内容 背景知识¾网间进程通信概念¾套接字编程实验内容¾UDP通信¾基于TCP的客户/服务器程序OSI模型与TCP/IP协议栈TCP协议 TCP的特点¾端到端、面向连接、全双工通信¾流接口、抽象成连续的字节流面向连接的可靠传输¾建立连接¾正确、顺序传送数据¾断开连接处理的问题¾IP数据报的丢失、重复、失序、延迟¾发送和接收速度的匹配¾系统重启动,一方连接信息丢失¾网络拥塞UDP协议 无连接¾不需要在通信前建立连接¾不使用控制报文¾传输开销低面向报文¾不将报文分割,也不合并¾UDP报文的大小影响了网络的利用率9过小造成报头比率过大9过大造成MTU分片尽力而为任意交互¾一对一、一对多、多对一和多对多Linux 的网络分层结构网络应用BSD 用户数据界面套接字INET 套接字接口界面TCPUDP协议分层IPPPP SLIP Socket ARP网络驱动网络服务的标识TCP/UDP端口号作为服务器程序标识¾服务器启动时,首先在本地主机注册自己使用的TCP或UDP端口号¾客户通过与服务器指定的TCP端口建立连接(或直接向服务器指定的UDP端口发送信息)来访问特定服务¾运行服务器程序的主机收到信息后,将其转交给注册该处理端口的服务器程序端口的服务器程序处理¾网络进程标识方法9(协议,本地地址,本地端口号)¾完整网间通信标识方法9协议,本地地址,本地端口号,远地地址,远地端口号)网络地址通常主机地址由网络ID和主机ID组成¾在TCP/IP协议中用32位整数值表示¾TCP和UDP均使用16位端口号标识用户进程某一主机可与多个网络相连,必须指定一特定网络地址网络上每一台主机应有其唯一的地址每一主机上的每一进程应有在该主机上的唯一标识每主机上的每进程应有在该主机上的唯标识符协议端口端口是一种抽象的软件结构,用于标识通信的进程 客户程序或服务进程使用其发送和接收信息TCP和UDP的端口号相互独立端口号分配¾全局分配:由一个公认的中央机构根据用户需要进行统一分配,并将结果公布于众¾本地分配:进程需要访问传输层服务时,向本地操作系统提出申请,操作系统返回一个本地唯一的端口号¾TCP/IP端口号分配方法:综合上述两种方式9保留端口(<256):以全局方式分配给服务进程9自由端口:以本地方式进行分配客户/服务器交互模型服务器程序¾被动地等待请求并做出响应客户程序¾向服务器发出服务请求客户/服务器程序特性对比服务器请求处理流程循环服务器方案—系统资源要求不高在处理一个请求时其他请求必须等待般针对于面向无连接的客户/服务器模型一般针对于面向无连接的客户服务器请求处理流程并发服务器方案—系统资源要求较高实时性和灵活性是该方案的最大特点般针对于面向连接的客户/服务器模型一般针对于面向连接的客户主要内容 背景知识¾网间进程通信概念¾套接字编程实验内容¾UDP通信¾基于TCP的客户/服务器程序Linux的网络分层结构功能说明 套接字(Socket)接口¾Socket接口是应用程序同TCP/IP协议栈的接口¾源自加州大学Berkeley分校的BSD UNIX9很多语法特性源自UNIX¾Socket并不是TCP/IP标准的组成部分¾目前已成为事实上的工业标准9UNIX系列系统提供Socket9Windows系列、Macintosh系列、Solaris等亦提供TCP/IP网络套接字应用层套接字层流套接字数据报套接字TCP UDPIP层网络层socket基本概念TCP/IP网络的API¾定义一组函数/例程,支持TCP/IP网络应用程序开发 一种文件描述符Socket数据传输是一种特殊的¾I/O¾与数据通信相关的系统调用是read()/write()基于socket的端到端通信¾形式9(IP, PORT)¾网络进程标识本地端9<协议, 本地地址, 本地端口>¾网间通信标识9<协议, 本地地址, 本地端口, 远程地址, 远程端口>¾端口分类9公认端口:小于256的端口才能作为保留端口9注册端口9动态和/或私有端口socket基本功能支持多种协议族面向连接的服务和无连接的服务地址的表示(数据结构)主机字节顺序和网络字节顺序基本socket APIsocket APIsocket()-创建一个新的Socketclose() -关闭一个Socketbind() 将服务器(IP, Port)赋予Socketbind()-将服务器(IP Port)listen() -等待到来的客户连接请求(TCP)()接受客户连接请求并建立连接(accept() -接受客户连接请求并建立连接(TCP) connect() -向服务器发出连接请求send() -发送数据recv()-接收数据recv() 接收数据套接字类型 流套接字(SOCK_STREAM)¾可靠的、面向连接的通信¾使用TCP协议数据报套接字(SOCK_DGRAM)¾无连接服务¾使用UDP协议原始套接字(SOCK_RAW)(SOCK RAW)¾允许对底层协议如IP、ICMP直接访问sockaddr 结构定义功能¾保存socket 信息结构struct sockaddr {{unsigned short sa_family ; /* 地址族,AF_xxx */ char char sa_data sa_data[14]; /* [14]; /* 协议地址*/ };说明¾sa_family 一般为AF_INET (表示TCP/IP )sa data ¾sa_data 包含socket 的IP 地址和端口号¾/include//include/linux linux//socket.hsockaddr insockaddr_in结构定义 功能k dd¾sockaddr的另一种表示形式 结构struct sockaddr in{struct in_addr{ __u32 s_addr;struct sockaddr_in {short int sin_family; /* 地址族*/unsigned short int sin_port; /* 端口号*/ struct in addr sin addr; /* IP*/ };st uct_add s_add;/地址/unsigned char sin_zero[8]; /* 填充0 以保持与struct sockaddr同样大小*/};};说明¾sin_zero用于将sockaddr_in结构填充到与struct sockaddr等长,可用bzero( )或memset( )函数将其置为0¾当sin_port = 0时,系统随机选择一个未被使用的端口号¾s addr = INADDR ANY IP当__时,表示填入本机地址¾指向sockaddr_in的指针和指向sockaddr的指针可以相互转换Linux支持的协议和地址族地址协议协议描述AF_UNIX PF_UNIX Unix域AF_INET PF_INET TCP/IP(V4)AF_INET6PF_INET6TCP/IP(V6)AF INET6PF INET6AF_AX25PF_AX25业余无线电使用的AX.25 AF_IPX PF_IPX Novell的IPXAF IPX PF IPX N llAF_APPLETALK PF_APPLETALK AppleTalk DDSAF_NETROM PF_NETROM业余无线电使用的NetRom字节顺序主机字节顺序(HBO,Host Byte Order)¾不同的机器HBO不相同,与CPU设计有关¾Motorola 68k系列,HBO与NBO相同¾Intel x86系列,HBO与NBO相反网络字节顺序(NBO,Network Byte Order)Network Byte Order ¾使用统一的字节顺序,避免兼容性问题字节顺序转换函数头文件#i l d t ti t/i h ¾#include <#include <netinet netinet//in.hin.h>> 函数原型uint32t htonl htonl(uint32(uint32t hostlong ¾uint32_t uint32_t htonl htonl(uint32_t (uint32_t hostlong hostlong););9把32位值从主机字节序转换成网络字节序¾t uint16t htons htons(uint16t (uint16t hostshort hostshort);_(_);9把16位值从主机字节序转换成网络字节序¾uint32_t uint32_t ntohl ntohl(uint32_t (uint32_t hostlong hostlong););9把32位值从网络字节序转换成主机字节序¾uint16_t uint16_t ntohs ntohs(uint16_t (uint16_t hostshort hostshort););9把16位值从网络字节序转换成主机字节序 说明h host,n ¾h 代表host, n 代表network ¾s 代表short ,l 代表longsocket()函数功能¾创建一个套接字¾#include <sys/socket.h>函数原型¾int socket(int domain, int type, int protocol);参数说明¾domain:应用程序所在主机使用的通信协议族,即地址族yp:套接字类型,可选流式、数据报式或原始式套接字¾type¾protocol:使用的特定协议,通常设置为0 ,让内核根据指定的类型和协议族使用默认的协议返回值¾成功时,返回一个大于等于0的文件描述符¾失败时,返回一个小于0的值socket()函数代码框架int main(){……int sockfd;;if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){perror(“socket”);exit(1);}……}套接字选项函数原型¾int getsockopt(int sockfd, int level, int optname, void*optval, socklen_t*optlen)sockfd,int level,int optname,const*optval,¾int setsockopt(int sockfd, int level, int optname, const void optval, socklen_t*optlen)功能¾控制套接字行为,如修改缓冲区的大小、传输方式等参数说明¾level:指定控制套接字的层次9SOL_SOCKET:通用套接字选项IPPROTO IP9IPPROTO_IP:IP选项9IPPROTO_TCP:TCP选项p:指定控制的方式(选项的名称)¾optname¾optval:获得/设置套接字选项SOL SOCKETSOL_SOCKET参数选项SO_BROADCAST允许发送广播数据intSO BROADCAST intSO_DEBUG允许调试intSO_DONTROUTE不查找路由intSO_ERROR获得套接字错误intSO ERROR intSO_KEEPALIVE保持连接intSO_LINGER延迟关闭连接struct linger _SO OOBINLINE带外数据放入正常数据流intSO_RCVBUF接收缓冲区大小intSO_SNDBUF发送缓冲区大小intSO_RCVLOWAT接收缓冲区下限intSO_SNDLOWAT发送缓冲区下限intSO_RCVTIMEO接收超时struct timeval SO_SNDTIMEO发送超时struct timeval SO_REUSERADDR允许重用本地地址和端口int允许重用本地地址和端SO_TYPE获得套接字类型intSO_BSDCOMPAT与BSD系统兼容intIPPROTO IP IPPRO TCPIPPROTO_IP与IPPRO_TCP参数选项 IPPROTO_IP¾IP_HDRINCL9在数据包中包含IP首部IP OPTINOS¾IP_OPTINOS9IP首部选项_¾IP TOS9服务类型¾IP_TTL9生存时间IPPRO_TCPTCP MAXSEG¾TCP_MAXSEG9TCP最大数据段的大小TCP NODELAY¾TCP_NODELAY9不使用Nagle算法套接字选项示例更改发送/接收缓冲区大小¾接收缓冲区int nRecvBuf=32*1024;//设置为32Ksetsockopt(s,SOL_SOCKET,SO_RCVBUF,(constchar*)&nRecvBuf,sizeof(int));¾发送缓冲区int nSendBuf=32*1024;//设置为32Kt k t(SOL SOCKET SO SNDBUF(tsetsockopt(s,SOL_SOCKET,SO_SNDBUF,(constchar*)&nSendBuf,sizeof(int));¾说明9对于客户,SO_RCVBUF选项必须在connect之前设置对于服务器SO RCVBUF9对于服务器,SO_RCVBUF选项必须在listen前设置bind()函数功能¾将套接字地址与所创建的套接字号联系起来¾#include <sys/socket.h>函数原型¾int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen); 参数说明¾sockfd :调用socket 返回的文件描述符¾my addr struct sockaddr IP y_:指向的指针,保存地址(即端口和地址) 信息¾addrlen :设置为sizeof(struct sockaddr)返回值¾成功时,返回0¾失败时,返回-1bind()函数int main(){int sockfd;struct sockaddr_in my_addr; /* 本机地址信息*/……if (bind(sockfd, (struct sockaddr *)&my_addr,sizeof(struct sockaddr))== -1){perror(“bind”);exit(1);}……connect()函数功能¾建立套接字连接¾#include <sys/socket.h>函数原型¾int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen););参数说明¾sockfd:调用socket返回的文件描述符¾serv_addr:保存着目的地端口和IP 地址的数据结构struct sockaddr ¾addrlen:设置为sizeof(struct sockaddr)返回值¾成功时,返回0¾失败时,返回-1connect()函数int main(){(){int sockfd;sockaddr in serv addr;/**/ struct sockaddr_in serv_addr;/服务器地址信息/……if (connect(sockfd, (struct sockaddr*)&serv_addr,sizeof(struct sockaddr))== -1){perror(“connect”);exit(1);}……}listen()函数功能¾用于面向连接服务器,表明它愿意接收连接¾#include <sys/socket.h>函数原型¾int listen(int s, int backlog);参数说明参数说¾sockfd:调用socket返回的文件描述符¾backlog:在进入队列中允许的连接数目,在发生错误的时候返回-1返回值¾成功时,返回0¾失败时,返回-1listen()函数int main(){int sockfd;……if (listen(sockfd, BACKLOG)== -1) { {perror("listen"); exit(1);}……} }accept()函数功能¾建立套接字连接¾#include <sys/socket.h>函数原型¾int accept(int s, struct sockaddr *addr, socklen_t*addrlen);*dd l)参数说明kfd k t¾sockfd:调用socket返回的文件描述符¾addr:指向局部的数据结构sockaddr_in的指针sizeof(struct sockaddr in)¾addrlen:设置为sizeof(struct sockaddr_in)返回值socket¾成功时,返回一个socket 端口¾失败时,返回-1accept()函数int main() {int sockfd, client_fd;sockfd client fd;struct sockaddr_in remote_addr;/* 客户端地址信息*/……while(1) {sin_size= sizeof(struct sockaddr_in);if ((client_fd= accept(sockfd, (struct sockaddr*)&remote_addr, &sin_size))== -1){p(p);;perror("accept"); continue;}printf("from %s\n", inet_ntoa(remote_addr.sin_addr));……}……}write()函数函数原型¾ssize_t write(int fd,const void*buf,size_t nbytes)功能¾将buf中的nbytes字节内容写入文件描述符fd返回值¾成功时返回写的字节数¾失败时返回-1,并设置errno变量说明¾write的返回值大于0,表示写了部分或者是全部的数据¾返回的值小于0,表示出现错误9如果错误为EINTR ,表示在写的时候出现中断错误表络连接出现问题9如果为EPIPE,表示网络连接出现问题基于write()函数的socket写实现read()函数函数原型¾ssize_t read(int fd,void*buf,size_t nbyte)功能¾从fd中读取内容返回值¾读成功时,返回实际所读的字节数9如果返回的值是0表示已经读到文件的结束,¾出错时,返回值小于0说明读是由中断引起的9如果错误为EINTR,说明读是由中断引起的9如果是ECONNREST表示网络连接出了问题基于read()函数的socket读实现send()函数功能¾用于流式套接字或者数据报套接字的通讯¾#include <sys/#include <sys/types.h types.h>>#include <sys/<sys/socket.h socket.h>>¾#include sys/sys/socket.h socket.h 函数原型¾ssize t send(send(int int sockfd sockfd, const void *, const void *buf buf, , size t size len len, , int int flags);_(,,_,g ); 参数说明¾sockfd :发送数据的套接字描述符¾msg :指向发送数据的指针¾len :数据长度fl ¾flags:一般设置为0 返回值¾成功时,返回实际发送的数据的字节数¾失败时,返回-1send()函数if (!fork()){/* 子进程代码段*/if (send(client_fd, "Hello, you are connected!\n", 26, 0)== -1) if(d(li fd"H ll d!\"260)1) perror("send");close(client_fd);close(client fd);exit(0);}recv()函数功能¾用于流式套接字的通讯¾#include <sys/#include <sys/types.h types.h>>¾#include <sys/#include <sys/socket.h socket.h>>y 函数原型¾ssize_t recv recv((int sockfd sockfd, void *, void *buf buf, , size_t size_t len len, , int int flags ); 参数说明¾sockfd :要读的SOCKET 描述符¾buf :要读的信息的缓冲区¾len :缓冲的最大长度¾flags :一般设置为0返回值¾成功时,返回实际接收到的数据的字节数¾失败时,返回-1send()/recv()中的flags说明MSG_DONTROUTE¾是send()的使用标志,不查找路由表,表示目的主机在本地网络MSG_OOB¾接受或者发送带外数据MSG_PEEK¾是recv()的使用标志,查看数据,并不从系统缓冲区移走数据MSG_WAITALL¾是recv()的使用标志,表示等待所有数据,阻塞式接收,直到满足条件或发生错误9读到指定字节时,正常返回,返回值等于len9读到文件尾,正常返回,返回值小于len9操作错误时,返回-1recv()函数#define MAXDATASIZE 100 /*每次最大数据传输量*/……int main(int argc, char *argv[])i t i(i t h*[]){int recvbytes;int recvbytes;char buf[MAXDATASIZE];……if ((recvbytes = recv(sockfd, buf, MAXDATASIZE, 0)) == -1) {perror("recv"); exit(1);("")it(1)}……}sendto()函数功能¾用于数据报套接字的通讯¾#include <sys/#include <sys/types.h types.h>><sys/#include <sys/socket h socket h>¾#include <sys/#include <sys/socket.h socket.h>>函数原型i t dt i t kfd t id *i t l i d i t ¾int sendto sendto((int sockfd sockfd, const void *, const void *msg msg, , int int len,unsigned int flags,const struct sockaddr *to , int tolen );参数说明¾to :目地机的IP 地址和端口号信息sockaddr))¾tolen :常被赋值为sizeof (struct sockaddr sockaddr) ) 返回值¾成功时,返回实际发送的数据的字节数¾失败时,返回-1。