《2022年2022年计算机网络课上机题 .pdf》由会员分享,可在线阅读,更多相关《2022年2022年计算机网络课上机题 .pdf(14页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、计算机网络课上机题一、实验目的BSD socket 目前已经被广泛移植到各个平台,因此熟悉了BSD socket 的编程界面,对以后的学习、工作都有很重要的现实意义。了解 BSD socket 编程界面, 熟悉 socket 相关的各种API 的使用, 如 socket, bind, listen, accept, connect, send, recv, sendto, recvfrom, htonl, ntohl, htons, ntohs 等。了解阻塞式IO 、非阻塞式 IO 概念与控制。二、 实验基础每个 socket 的应用,通常都有如下的API 的使用:socket 用于生成一个套
2、节字accept 接受一个连接请求,用于服务器端的编程connect 发起一个连接请求,用于客户端的编程send/sendto 发送信息recv/recvfrom 接收信息select 多路复用调用bind 将主机的地址 /端口信息与某个socket 相关联listen 进入监听状态close 关闭一个socket shutdown 断开连接fcntl 设置 socket 的选项htons 主机序到网络序的短整型ntohs 网络序到主机序的短整型通常的服务器端的编程:通常的客户端编程socket socket bind listen accept connect send/recv send/
3、recv shutdown shutdown close close IPv6 是对现有的Ipv4 的扩展,在编程界面上,都和v4 的类似,只是地址部分有变化。三、编程上机题目(注意:请用C 语言编程 ) 1. 写简单的 socket应用程序,应用的内容和形式可以自己决定。可以是基于client/server结构的,也可以是对等结构的。目的是熟悉基本的socket 应用程序的编写。基本要求:使用基本的API 函数。服务器端至少能够支持一个客户,客户端和服务器端能够互相发送/接收信息。可以选择udp 或者 tcp 协议。例 1:简单的回显程序,即客户端输入什么,服务器端能够回送什么例 2:两个人
4、的聊天程序,即你一言,我一语的那种。2. 套接字 Socket 应用。熟悉unix 环境下 socket 编程的几种编程的使用模式,阻塞式IO 的多客户端支持,非阻塞IO 的使用等。基本要求:名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 14 页 - - - - - - - - - 使用 select来实现多个客户端的多路复用,至少支持4 个以上的客户端。可以结合题目1一起做。例 1:可以写一个聊天室,功能能够实现多个人同时登录,进行聊天。登录时提示输入昵称,不允许重复
5、的登录,进入聊天室以后可以说话,每个里面的人都能看到。例 2:可以写一个HTTP的 Proxy ,功能是实现简单的Proxy 的功能,可以通过你的应用程序,进行 HTTP的访问。注意支持多个客户端。3. 编写简单多播应用程序。应用的环境不限。可以是视频流或者音频流或者其他形式的内容。基本的要求:使用基本的API 函数。客户端和服务器端之间的交互可以使用如下的结构:server-文件应用程序 - client |_网络 _| 文件可以是视频/音频流。至少能有两个以上的客户端能够接收到同步的信息并且播放。例 1:音频多播可以以音频文件为输入流,循环地通过服务程序播送;客户端从网络接收,并能够传递给
6、播放软件。例 2:视频多播同上,以视频文件为输入流。四、参考书籍Unix 网络编程电子工业出版社Linux 网络编程清华大学出版社Windows 网络编程机械工业出版社ftp:/202.38.75.11/EBooks/Unix_Programming/Windows网络编程技术特别致谢向计算机科学技术系2000 级研究生杨琛同学表示特别感谢。附录 :1. 简单的说明linux 下编写 socket 的应用程序比较简单,如果有不太清楚的调用,可以直接通过man socket等的使用来观察应该包含的头文件,函数的原型,以及正常时应该的返回值。编译通常的程序可以使用 (g)cc source.c o
7、 outfile 来进行,如果是c+的程序, g+ source.c o outfile 运行 : $./outfile 回车后台执行$./outfile & 回车Windows 下面的编程稍微麻烦一点,需要安装MSDN ,里面也有详细的每个函数的说明。在Platform SDK: WinSock 的部分。要编写Winsock 的应用程序应该包含头文件winsock.h 。然后在工程的设置的Link 里面加上winsock32.lib 。或者在程序中写上#pragma comment(lib, ” winsock32 ” ) 并且,每个Winsock 的应用程序都要进行Winsock 的初始化
8、, WSAStartup/WSACleanup 。具体的可以参考202.38.75.11 上的电子书。2. 部分中文材料:TCP/IP 编程接口介绍Linux/Unix :Socket 函数库Linux Socket 函数库是从Berkeley 大学开发的BSD UNIX系统中移植过来的。BSD Socket 接口是在众多Unix 系统中被广泛支持的TCP/IP 通信接口, Linux 下的 Socket 程序设计,除了微小名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 2 页,共
9、14 页 - - - - - - - - - 的差别之外,也适用于大多数其它Unix 系统。Socket 的使用和文件操作比较类似。如同文件的读、写、打开、关闭等操作一样,TCP/IP网络通信同样也有这些操作,不过它使用的接口不是文件描述符或者FILE* , 而是一个称做Socket的描述符。类似于文件操作,对于Socket ,也通过读、写、打开、关闭操作来进行网络数据传送。同时,还有一些辅助的函数,如域名/IP 地址查询、 Socket 功能设置等。以下是函数分类介绍(此介绍选自Linux manpage ,不当之处,请参阅原文):1. Socket 操作:Socket():分配Socket
10、 #include #include int socket(int domain, int type, int protocol); socket()函数分配一个Socket 句柄, 用于指定特定网络下、使用特定的协议和数据传送方式进行通信。 Socket 接口是不仅仅局限于TCP/IP 的,但是由于TCP/IP 的广泛使用,它们几乎被完全等同起来了。Socket 句柄分配以后,如果要开始TCP 通信,还需要建立连接。根据需要,可以主动地建立连接(通过 connect())和被动地等待对方建立连接(通过 listen()) ,在连接建立后才能使用读写操作通过网络连接进行数据交换。参数说明:do
11、main:domain 参数选择通信中使用的协议族,也就是网络的类型,可以是以下之一:AF_UNIX (UNIX内部协议 ) AF_INET (ARPA Internet协议,也就是TCP/IP 协议族,亦即我们实验中所使用的) AF_ISO (ISO 协议 ) AF_NS (Xerox Network Systems协议 ) AF_IMPLINK (IMP host at IMP link layer) type :数据传送的方式,可以是以下之一:SOCK_STREAM :保证顺序的、 可靠传送的双向字节数据流,最为常用, 也是 TCP 连接所使用的方式。SOCK_DGRAM :无连接的、不
12、保证可靠的、固定长度(通常很小)的消息传送。SOCK_SEQPACKET :顺序的、可靠的双向固定长度的数据包传送,只用于AF_NS 类型的网络中。SOCK_RAW :原始的数据传送,适用于系统内部专用的网络协议和接口,和SOCK_RDM 一样,只能由超级用户使用。SOCK_RDM :可靠的数据报传送,未实现。Protocol:protocol 参数指定通信中使用的协议。在给定 Socket 的协议族和传送类型之后,一般情况下所使用的协议也就固定下来,如下表所示,此时protocol 参数可使用缺省值0;但如果还有多个协议供选择,则必须使用protocol 参数来标识。协议族(仅考虑 IP 协
13、议族)传送类型protocol参数常量( /usr/include/linux/in.h)协议类型AF_INET SOCK_STREAM IPPROTO_TCP TCP SOCK_DGRAM IPPROTO_UDP UDP SOCK_RAW IPPROTO_ICMP ICMP 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3 页,共 14 页 - - - - - - - - - SOCK_RAW IPRROTO_RAW (raw) 返回值:正常执行时,返回Socket 描述符;否则
14、,返回-1,错误状态在全局变量errno 中。close():关闭 Socket #include int close(int fd); Socket 和文件描述符的关闭操作都是使用这个函数。参数说明:fd:Socket 描述符。返回值:正常时返回0,-1 表示出错。bind():给 Socket 指定本地地址#include #include int bind(int sockfd, struct sockaddr *my_addr, int addrlen); bind 函数给已经打开的Socket 指定本地地址。这个函数的使用有以下两种情况:如果此 Socket 是面向连接的,而且此So
15、cket 在连接建立过程中处于被动的地位,即己方程序使用listen 函数等待对方建立连接,对方用 connect 函数来向此Socket 建立连接, 这种情况下,必须用bind 给此 Socket 设定本地地址。在己方使用listen 函数时,除指定Socket 描述符之外,该 Socket 必须已经用bind 函数设定好了本地地址(包括IP 地址和端口号) ,这样,系统在收到建立连接的网络请求时,才能根据请求的目的地址,识别是通向哪个Socket 的连接,从而己方才能用此Socket 接收到发给此Socket 地址的数据包。不指定Socket 的本地地址,就无法将此Socket 用于连接建
16、立和数据接收。如果此 Socket 用于无连接的情形,同样也要求给该Socket 设定本地地址,这样,以后系统从网络中接收到数据后,才知道该送给哪个Socket 及其相对应的进程。参数说明:sockfd:Socket 描述符。Addrlen :my_addr 结构的长度。my_addr:用于侦听连接请求的本地地址。struct sockaddr 是一个通用型的结构,不仅包含TCP/IP协议的情况,同时也是为了适合于其它网络,如AF_NS 。由于它的这种通用性,它只是定义了一个一般意义上的存储空间,如/usr/include/linux/socket.h中所示:struct sockaddr u
17、nsigned short sa_family; /* address family, AF_xxx */ char sa_data14; /* 14 bytes of protocol address */ ; 当使用TCP/IP 协议(即Internet 协议)时,可用如下的struct 等价地代替struct sockaddr(/usr/include/linux/in.h ) :#define _SOCK_SIZE_ 16 /* sizeof(struct sockaddr) */ struct sockaddr_in short int sin_family; /* Address
18、family */ 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 4 页,共 14 页 - - - - - - - - - unsigned short int sin_port; /* Port number */ struct in_addr sin_addr; /* Internet address */ /* Pad to size of struct sockaddr. */ unsigned char _pad_SOCK_SIZE_ - sizeof(short int
19、) - sizeof(unsigned short int) - sizeof(struct in_addr); ; 在 Socket 程序中,等待建立连接一方的准备过程请参见编程实例,以及 listen()、 accept()的说明。返回值:正常时返回0,否则返回 -1,同时 errno 是系统错误码。listen():准备接受连接请求。#include int listen(int s, int backlog); 在用bind()给一个Socket 设定本地地址之后,就可以将这个Socket 用于接受连接请求,即listen() 。调用 listen() 之后,系统将给此Socket 配
20、备一个连接请求的队列,暂存系统接收到的、申请向此 Socket 建立连接的请求, 等待用户程序用accept()正式接受该请求。 队列长度,就由 backlog参数指定。如下面的简图所示:通信己方Me 通信对方Socket_Me Peer Sockets 连接请求暂存队列0- 连接建立请求1 - connect() Socket_peer_1 1- 连接建立请求2 - connect() Socket_peer_2 backlog-1- 连接建立请求n - connect() Socket_peer_n 如果短时间内向己方建立连接的请求过多,己方来不及处理,那么排在backlog 之后的请求将
21、被系统拒绝。因此,backlog 参数实际上规定了己方程序能够容许的连接建立处理速度。至于己方程序使用此Socket(及其指定的本地地址)实际建立连接的个数,由己方程序调用accept()的次数来决定,参见accept()的说明。参数说明:s:Socket 描述符。Backlog:连接请求暂存队列长度。返回值:正常时返回0;否则返回 -1,同时 errno 是系统错误码。accept:接受指定Socket 上的连接请求#include #include int accept(int s, struct sockaddr *addr, int *addrlen); 名师资料总结 - - -精品资
22、料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 5 页,共 14 页 - - - - - - - - - 在调用 listen() 之后,系统就在Socket 的连接请求暂存队列里存放每一个向该Socket(及其本地地址)建立的连接请求。 accept()函数的作用就是, 从该暂存队列中取出一个连接请求,用该 Socket的数据,创建一个新的Socket:Socket_New,并为它分配一个文件描述符。Socket_New 即标识了此次建立的连接,可被己方用来向连接的另一方发送和接收数据(write/read,s
23、end/recv) 。同时,原 Socket 仍然保持打开状态不变,继续用于等待网络连接请求。如果该Socket 的暂存队列中没有待处理的连接请求,根据Socket 的特征选项(是否non_blocking ) ,accept()函数将选择两种方式:如果该Socket 不是 non_blocking 型的, accept()将一直等待,直到收到一个连接请求后才返回;如果该Socket 是 non_blocking 型的,那么accept()将立即返回,但如果没有连接请求,只返回错误信息,不创建新的Socket_New。accept()返回后,如果创建了新的Socket_New 来标识新建立的连
24、接,那么参数addr 指定的结构里面将会有对方的地址信息,addrlen 是地址信息的长度。关于 accept()的进一步信息, 如: 如何检测某Socket 有无待处理的连接请求、如何在使用accept()接受连接请求之前先获取连接对方的地址、如何根据获取的对方地址信息拒绝该连接请求等,请参阅 Linux manual ,此处不再累述。参数说明:s:Socket 描述符。addr :accept()接受连接后,在addr 指向的结构中存放对方的地址信息。如果是AF_INET Socket,该地址信息就是对方的IP 地址和端口号。addrlen: 在调用 accept()之前, *addrle
25、n 必须被设置为addr 数据结构的合法长度。在 accept()返回之后, *addrlen 中是对方地址信息的长度。返回值:如果正常创建了一个新的连接,那么返回非负的整数:即新连接的Socket 描述符(注意,用于等待连接请求的原Socket 保持打开状态不变,可用于接收新的连接请求。) ; 否则,返回 -1,errno是系统错误码。connect:建立连接#include #include int connect(int sockfd, struct sockaddr *serv_addr, int addrlen ); 前面提到的函数,如bind、listen、connect 等,都是
26、用于被动地等待对方建立连接时需要使用的,而 connect()函数,则是主动地向对方建立连接时使用的。connect()使用一个事先打开的Socket,和目的方(即通信对方, 或称服务器一方) 地址信息, 向对方发出连接建立请求。一个完整的Socket通信发起过程可简单地图示为:主动发起方(客户方)被动接受方(服务方)listen(sock_w); 等待连接建立请求connect(sock_s) 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 6 页,共 14 页 - - - - -
27、 - - - - 发送连接建立请求 sock_d = accept();接受连接建立请求发送应答收到连接建立应答 此时,在sock_s和 sock_d 之间,一个连接就建立完毕。如果是SOCK_STREAM型的Socket,通常只用connect()建立一个正常的连接。但如果是SOCK_DGRAM型的 Socket,connect()函数并不象上图中那样向目的方发出连接建立请求,而只是简单地用给出的地址设置该Socket 的目的地址, 以后该 Socket 的无连接数据报就发往该目的地址。因此,对于 SOCK_DGRAM型的 Socket, 可以多次调用connect()来改变该 Socket
28、 的目的地址。SOCK_DGRAM型的 Socket 与本实验关系不大,故不再详述。参数说明:sockfd:Socket 描述符。serv_addr :通信目的方的地址。其格式参见bind() 的说明。Addrlen :目的地址长度。返回值:连接正常建立时返回0;否则,返回 -1,系统错误码在errno 中。send/recv:用 Socket 发送和接收数据#include #include int send(int s, const void *msg, int len, unsigned int flags); int sendto(int s, const void *msg, int
29、 len, unsigned int flags, const struct sockaddr *to, int tolen); int recv(int s, void *buf, int len, unsigned int flags); int recvfrom(int s, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen); 在连接建立完成后,通信双方就可以使用以上这些函数来进行数据的发送和接收操作。其中,send和 recv 用于连接建立以后的发送和接收;sendto和 recvf
30、rom 用于非连接的协议。对于非 non_blocking 型的 Socket,send 将等待数据发送完后才返回;对于non_blocking 型的Socket,send 将立即返回,用户程序需要用select()函数决定网络发送是否结束。类似地,对于非non_blocking 型的 Socket,若系统没有收到任何数据,recv 将等待接收数据到达后才返回;对于non_blocking 型的 Socket,recv 将立即返回,并返回错误信息或者接收到的数据字节数。sendto和 recvfrom 因为是非连接型的发送和接收,必须在参数中给出目的地址或者存放源地址的空间。名师资料总结 -
31、- -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 7 页,共 14 页 - - - - - - - - - 参数说明:s:Socket 描述符;msg, buf:存放接收或者发送数据的存储空间;len:接收或者发送数据的字节数;to,from: sendto 和 recvfrom 所使用的,目的方地址和存放源地址的空间;tolen,fromlen :目的地址和源地址空间大小。flag:通常设为0,详细说明请参见Linux Manual 。返回值:send/sendto返回实际发送的数据字节数,或者-1,
32、表示出错;recv/recvfrom 返回实际接收到的数据字节数,或者-1,表示出错。read/write :用系统文件操作进行Socket 通信#include ssize_t read(int fd, void *buf, size_t count); ssize_t write(int fd, const void *buf, size_t count); 在连接建立完成后,对于连接建立过程中被动的一方,在 accept()正常返回后,它返回一个新的 Socket,并且为该Socket 分配了一个文件描述符;对于连接请求发起方,connect()正常返回后,相应的Socket 中也包含有
33、已分配的文件描述符。因此,可以使用标准的Unix文件读写函数read()/write() 来进行 Socket 通信。 要注意的是, 由于网络数据和磁盘文件不一样,不是已经准备好的,因此, 每次读写操作不一定能传送完指定长度的数据,需要由程序反复进行剩余部分的传送。另外,文件描述符是较底层的文件操作参数,不同于C 语言中常用的FILE* 。FILE* 是使用fread/fwrite 函数来进行读写操作的。参数说明:fd:文件或者Socket 描述符。buf:数据缓冲区。count:数据字节数。返回值:正常时, 返回所读写的字节数(注意, 可能小于 count 参数指定的数目) ;否则, 返回
34、-1,errno是系统错误码。getsockopt/setsockopt:获取、设置Socket 特征选项。#include #include int getsockopt(int s, int level, int optname, void *optval, int *optlen); int setsockopt(int s, int level, int optname, const void *optval, int optlen); 由于在普通的Socket 编程中很少涉及这些选项,在这里不作介绍。non_blocking 特性:由于前面多处提到non_blocking 特性,这里
35、介绍一下如何设置这种特性。在这里,我们又可以看到 Socket 和文件描述符在Unix 系统中的相似性。实际上non_blocking 特性也是通过Unix 文件操作函数来设置的:名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 8 页,共 14 页 - - - - - - - - - #include #include fcntl(socket, F_SETFL, O_NONBLOCK); 数据格式转换#include unsigned long int htonl(unsigned
36、 long int hostlong); unsigned short int htons(unsigned short int hostshort); unsigned long int ntohl(unsigned long int netlong); unsigned short int ntohs(unsigned short int netshort); 数据格式转换函数提供和硬件平台无关的、主机数据字节顺序和网络字节顺序之间的转换。由于各种平台CPU 结构的不同,在不同的硬件平台下,主机的字节顺序有两种情况:Intel 80 x86和 SUN Sparc CPU 的低位在前格式和M
37、otorola CPU(68000、PowerPC)等的高位在前格式。网络数据交换要求网络中所有的int 型数据都有统一的字节顺序:高位在前格式,因此在Socket 函数库中提供了以上统一的字节顺序转换函数。在 Socket 程序中使用的地址数据,如端口号等,都必须遵循这样统一的字节顺序。因此,在本实验的例子程序中,在bind()函数、 connect()函数等涉及struct sockaddr_in 地址数据的场合,都可以看到以上转换函数的使用,以加强源程序的可移植性。主机名字 /地址数据查询为配合 DNS 的使用,尽量方便 Internet 主机名字的记忆, 避免使用烦琐的数字式IP 地址
38、, Socket函数库提供了方便的主机名字查询函数。struct hostent struct hostent 是一个关于主机地址信息的数据结构,其中包含从DNS 服务器得到的比较全面的主机信息。 gethostbyname()和 gethostbyaddr()都返回这样的数据结构。实际使用时,可用此结构中的地址信息来设置bind() 和 connect()函数参数中的struct sockaddr_in 中的地址,以支持DNS 名字的使用。参见本实验的具体示例。#include struct hostent char *h_name; /* official name of host */
39、char *h_aliases; /* alias list */ int h_addrtype; /* host address type */ int h_length; /* length of address */ char *h_addr_list; /* list of addresses from name server */ ; #define h_addr h_addr_list0 /* address, for backward compatibility */ 这其中最常用的是h_addr,即主机的缺省地址(因为该主机名字可能对应多个地址)。gethostbyname #
40、include struct hostent *gethostbyname(char *name); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 9 页,共 14 页 - - - - - - - - - 根据 DNS 名字,查找主机地址信息。name可以是 DNS 名字,如 ” ”,也可以是 IP 地址串: ”202.38.64.2 ”。gethostbyaddr #include struct hostent *gethostbyaddr(char *addr; int len
41、, int type); 根据 IP 地址查找主机地址信息。addr 是整数格式的IP 地址指针,如:unsigned char addr4202,38,64,2 ,在 Internet 协议中, len 必须为 4,type 必须为 AF_INET 。要注意的是: 如果只知道主机的IP地址, 而且 DNS 服务器中没有登记该主机,用 gethostbyname总能得到适当的主机地址信息,它只需要简单地将ASCII 形式的 IP 地址转换为二进制格式。但如果使用gethostbyaddr,却得不到所需要的地址信息,因为此函数完全依靠DNS 服务器进行IP 到DNS 名字的转换,不作其它的处理。
42、关于 Socket 编程接口,就介绍以上这些。作为普通的TCP/IP 应用,它们已经足够了。在本实验的示例中, 可以看到它们的具体应用。关于 Socket 接口的进一步资料,请参考更详细的资料,如 Linux Manual 等。Windows:Winsock 函数库Winsock 编程接口是直接从Socket接口移植过来的, 以上介绍的Linux Socket 函数, 在 Winsock环境下都可以直接使用(除了不支持AF_UNIX协议簇 Socket 和 struct sockaddr_un 地址结构之外)。但是,由于Windows 环境的特点, Microsoft 作了相当的扩充,增加了以
43、下一些功能的函数: Winsock 驱动程序的检测、初始化、清除函数,和错误代码函数(因为Windows 环境下没有全局的错误代码变量errno) , 如 WSAStartup() 、 WSACleanup() 、 WSAGetLastError() 、WSASetLastError() ;针对Windows 窗口界面的异步编程方式,提供了一些异步的主机数据查询函数,如 WSAAsyncGetHostByAddr()、WSAAsyncGetHostByName() 等;对于数据接收和发送,也提供了异步的操作方式,如WSAAsyncSelect() 、WSAIsBlocking()、WSASet
44、BlockingHook()、WSAUnhookBlockingHook()、WSACancelBlockingCall()、WSACancelAsyncRequest() 等。值得提出的是, 在 Windows95/NT 环境下,其Console 应用程序 (一种可以在Win95/NT DOS窗口下运行的32 位程序, 当然,它仍然有DOS 程序的 1MB 内存限制) 可以直接使用Unix Socket接口进行Socket 程序设计(仅需要增加WSAStartup 和 WSACleanup 的使用), 在我们的校园网上,就有经过这样改造的Win95 环境下的BBS 客户程序。程序示例在这里,
45、我们给出windows 环境下两个简单的Socket 通信程序的例子,一个是服务程序,它打开一个端口等待接收,并原封不动地传回所收到的数据;另一个例子是客户程序,它建立TCP连接到服务器,将用户的输入一行一行地发送给服务器,并显示服务器发送回来的数据。实际实验时,最好不要完全照搬这里的代码,那只能算是完成了实验的基本操作。这里强调的是大家对TCP/IP 通信编程的理解和创意。Windows sock 示例一:使用域名或IP 地址发送数据名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第
46、10 页,共 14 页 - - - - - - - - - #include #include #include #include #include void main(int argc,char *argv) char buf65535; struct sockaddr_in client; struct hostent *hp; int s; unsigned long ip_addr; int sendlen; int pktlen; int i; int waittm; unsigned long sendtimes; struct timeb starttime; struct ti
47、meb endtime; float timespers; struct timeval tv; fd_set rfds; WSADATA wsa_dat; if(argch_addr,hp-h_length); if(s=socket(AF_INET,SOCK_STREAM,0)0) perror(Socket(); exit(0); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 11 页,共 14 页 - - - - - - - - - client.sin_family=AF
48、_INET; client.sin_port=htons(atoi(argv2); if(connect(s,(struct sockaddr*)&client,sizeof(client)0) perror(Connect(); closesocket(s); exit(0); waittm=atoi(argv4); pktlen=atoi(argv3); for(i=0;ipktlen;i+) bufi=i; sendtimes=0; ftime(&starttime); while(1) if(sendlen=send(s,buf,pktlen,0)=0) perror(Send();
49、break; sendtimes+; if(kbhit() break; ftime(&endtime); closesocket(s); WSACleanup(); printf(send times:%uln,sendtimes); printf(time used:%d seconds and %d milisecondsn,endtime.time-starttime.time ,endtime.millitm-starttime.millitm); printf(%f times per secondn,timespers=sendtimes/(float)(endtime.time
50、- starttime.time) +(float)(endtime.millitm-starttime.millitm)/1000); printf(%d Bytes per packetn,pktlen); printf(%f Bits per secondn,timespers*pktlen*8); return; Windows socket示例二:接收数据#include #include #include #include #include main(int argc, char *argv) 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - -