Microsoft Word - VC网络编程全文.doc
|
|
|
- 桓俱 廖
- 8 years ago
- Views:
Transcription
1 第 2 章扫描可控计算机 在上一章我们提到过一款软件 电子教室, 其最主要的功能就是教师可以通过教师机程序控制和管理学生机, 实现课堂统一教学的目的 教师机和学生机要进行通信, 首先需要建立通信连接, 那么, 教师机怎样找到学生机, 并与学生机建立通信连接呢? 本章通过简单的通信程序实现扫描局域网内可控计算机的功能 扫描可控计算机功能实现分析 WinSock 通信编程技术 MFC 网络通信编程技术 2.1 功能需求分析设计 扫描可控计算机的功能分析 : 教师机主动联系学生机, 如果不能与学生机建立联系, 则说明学生机端没有运行该程序 ( 或出现错误 ), 该学生机不在可控范围 ; 反之, 如果教师机与学生机成功地取得了联系, 则证明学生机已启动程序, 处于可控状态 教师机扫描学生机时, 应该可以设置扫描范围, 例如一个 IP 地址范围, 教师机与范围内的所有学生机逐一联系, 判断其是否处于可控状态, 将处于可控状态的学生机显示在教师机端的程序界面上 该功能实现的前提 : 有两个应用程序, 一个运行在教师机, 一个运行在学生机 教师机和学生机之间网络连通 根据功能分析简单设计该程序的界图 2-1 教师机端程序界面面, 并用 Visio 软件画出来, 如图 2-1 和图 2-2 所示
2 16 Visual C++ 网络编程技术 图 2-2 学生机端程序界面 2.2 关键技术分析与核心程序 在开始做一个程序开发时, 首先应分析该程序的核心功能 ( 即该程序要干什么 ), 然后分析该功能在技术上是否能够实现, 需要采用什么技术来实现 解决了核心技术问题后, 剩下的就是工作量的问题了 考虑一下扫描可控计算机功能, 其核心技术就是两台联网的计算机之间进行通信, 那么采用什么技术实现网络通信呢? 目前最通用的网络编程接口就是套接字 (Socket) 最初, 套接字是由加利福尼亚大学伯克利分校开发的, 他们为了在 UNIX 操作系统下实现 TCP/IP 协议, 而开发了这样一个调用网络操作的编程接口, 也就是一套 API( 应用程序接口 ), 被称为 Socket 接口 现在 Socket 接口几乎是 TCP/IP 网络标准 API, 很多基于 TCP/IP 的网络应用程序都是基于 Socket 而编写的 使用 WinSock 编程实现为更清楚地说明使用 WinSock 进行面向连接的通信原理, 我们以电信局的普通电话服务为比较对象进行说明 : (1) 电信局提供电话服务类似通信程序的 Server 端, 普通电话用户类似通信程序的 Client 端 (2) 首先电信局必须建立一个电话总机 这就相当于必须在 Server 端建立一个 Socket ( 套接字 ), 这一步通过调用 socket() 函数实现 (3) 电信局必须给电话总机分配一个号码, 以便使用户能够拨通该号码得到服务 同时, 用户必须知道该总机的号码, 才能拨通该电话 同样, 通信程序在 Server 端也要为这一套接字指定一 port( 端口 ), 同时, 连接该 Server 程序的 Client 程序必须知道该端口 指定端口通过调用 bind() 函数实现 (4) 接下来电信局必须使总机开通并使总机能够高效地监听用户拨号, 如果电信局所提供服务的用户数太多, 你会发现拨打电信局总机老是忙音, 通常电信局内部会使该总机对应的电话号码连到好几个负责交换的处理中心, 在一个处理中心忙于处理当前的某个用户时, 新到用户可自动转到其他处理中心得到服务 同样通信程序的 Server 端也要使自己的套接字绑定端口设置成监听状态, 这是通用 listen() 函数实现的,listen() 的第二个参数是等待队列数, 就如同你可以指定电信局建立几个负责交换的处理中心 (5) 用户知道了电信局的总机号后就可以进行拨打请求得到服务 在 WinSock 的世界里, 作为 Client 端是要先用 socket() 函数建立一个套接字, 然后调用 connect() 函数进行连接 (6) 电信局的总机接受了这用户拨打的电话后负责接通用户的线路, 而总机本身则再回到等待的状态 Server 也是一样, 调用 accept() 函数进入监听处理过程,Server 端的代码即
3 在此处暂停, 一旦 Server 端接到申请后系统会建立一个新的套接字来为此连接服务, 而原先的套接字则再回到监听状态 (7) 当你电话讲完了, 就可以挂上电话, 彼此间也就离线了 Client 和 Server 间的套接字的关闭也是如此 ; 这个关闭离线的动作, 可由 Client 端关闭 有关闭套接字的函数为 closesocket() 从以上情况可以看出在服务器端建立一个套接字, 并进入实际的监听步骤的过程如下 : socket()->bind()->listen()->accept(), 在 accept() 后, 在 Server 端将生成一个新的套接字, 然后 Server 将继续进入 accept() 状态,Server 端程序用这个新的套接字来进行与 Client 端的通信, 用 recv() 函数接收数据,Client 端程序则通过 send() 函数来发送数据 在客户端也是采取类似的过程, 其调用 Winsock 的过程如下 :socket()->connect() ->send(), 首先建立一个 Socket, 然后用 connect() 函数将其与 Server 端的 Socket 连接, 连接成功后调用 send() 发送信息 面向连接的套接字通信过程如图 2-3 所示 图 2-3 面向连接的套接字通信过程 核心程序 WinSock 实现基于 TCP 的客户端 / 服务器通信 此实例目的是验证是否能够按照上面的通信过程通过 C++ 编码实现两个程序间的网络通 信, 实例分成两个程序, 一个是服务器程序 MyServer, 一个是客户端程序 MyClient 第 2 章扫描可控计算机 17
4 18 Visual C++ 网络编程技术 两个程序可以互相发送和接收数据 程序运行结果如图 2-4 和图 2-5 所示 图 2-4 服务器端程序运行结果 图 2-5 客户端程序运行结果 从上面的程序运行结果可以看到, 首先服务器端程序启动, 等待客户端的请求, 客户端 发出连接请求, 双方成功建立连接后, 客户端发送给服务器端一句话 Are You Ready? 服 务器端回复客户端 ok 因为这两个程序都是没有图形用户界面的 Console 程序, 因此在新建工程时, 要选择 Win32 Console Application 类型 服务器端程序代码清单 : #include "stdio.h" #include <winsock2.h> #pragma comment(lib,"ws2_32.lib") int main(int argc, char* argv[]) printf(" 服务器端程序已启动, 等待客户请求的到来...\n"); // 初始化 WinSock 为 2.0 版本 WSADATA wsadata; int ret; if((ret=wsastartup(makeword(2,2),&wsadata))!=0) printf(" 初始化 WinSock 出错 "); return 0; // 定义两个 socket 变量, 一个用来监听, 一个用来建立连接和提供服务 SOCKET listensocket,acceptsocket; // 设置服务器 客户的地址和端口 struct sockaddr_in serv,cliet; // 创建监听 socket
5 listensocket=socket(af_inet,sock_stream,0); if(listensocket==invalid_socket) printf(" 建立 socket 出错 \n"); return 0; // 设置服务器地址信息 serv.sin_family=af_inet; serv.sin_port=htons(8888); // 设置监听端口是 8888 serv.sin_addr.s_addr=htonl(inaddr_any); // 将监听 socket 与服务器地址绑定 if(bind(listensocket,(lpsockaddr)&serv,sizeof(serv))==socket_error) printf(" 绑定出错 \n"); return 0; // 开始监听 if(listen(listensocket,5)==socket_error) printf(" 监听出错 \n"); return 0; // 等待客户连接请求, 如有连接请求到来, 则用 acceptsocket 与其建立连接, 进行通信 int len=sizeof(cliet); acceptsocket=accept(listensocket,(struct sockaddr *)&cliet,&len); if(acceptsocket==invalid_socket) printf(" 建立连接出错 \n"); return 0; // 接收数据 char buf[1024]; ret=recv(acceptsocket,buf,sizeof(buf),0); if(ret==0) return 0; char str[1024]=0; printf(" 来自客户端的信息 :"); printf(buf); printf("\n"); // 发送数据 memset(buf,0,sizeof(buf)); strcpy(buf,"ok"); ret=send(acceptsocket,buf,sizeof(buf),0); if(ret==socket_error) printf(" 发送数据出错 \n"); // 准备一个长度为 1024 的字符数组, 用来接收数据 第 2 章扫描可控计算机 19
6 20 Visual C++ 网络编程技术 return 0; // 关闭 socket closesocket(acceptsocket); closesocket(listensocket); WSACleanup(); 代码解析 : 头文件 #include <winsock2.h> #pragma comment(lib,"ws2_32.lib") 使用 WinSock2 进行开发, 需要头文件 <winsock2.h> 和库文件 "ws2_32.lib" 的支持 WSAStartup WSAData 和 WSACleanup 函数 WSAStartup 函数 : 功能为初始化 WinSock, 在使用套接字函数前, 都应该进行此函数的调用 其本质是调 入合适的 WinSock 动态链接库 其函数原型如下 : int WSAStartup( WORD wversionrequested, LPWSADATA lpwsadata ); 参数 wversionrequested:winsock 版本, 其低字节表示主版本号, 高字节表示次版本 号 一般使用宏 MAKEWORD 来表示 例如 MAKEWORD(2,2) 表示版本 2.2 参数 lpwsadata:wsadata 结构指针, 它用来存储套接字信息 其结构定义如下 : WSAData 结构体定义 : typedef struct WSAData WORD wversion; WORD whighversion; char szdescription[wsadescription_len + 1]; char szsystemstatus[wsasys_status_len + 1]; unsigned short imaxsockets; unsigned short imaxudpdg; char FAR * lpvendorinfo; WSADATA, * LPWSADATA; WSACleanup 函数 : // 版本 // 版本 // 描述 // 系统状态 //WinSocket2 及以后已忽略 //WinSocket2 及以后已忽略 //WinSocket2 及以后已忽略 当应用程序不需再使用 WinSock API 的任何函数时, 需要调用 WSACleanup() 函数将其 从 Windows Sockets 的实现中注销, 以便释放为该应用程序或者 DLL 分配的任何资源 对应 每个 WSAStartup() 函数, 必须有一个 WSACleanup() 函数的调用 WSAStartup 和 WSACleanup 是成对出现的 其函数原型如下 : int WSACleanup(void); 结构体 sockaddr_in struct sockaddr_in short sin_family; u_short sin_port; struct in_addr sin_addr;
7 char ; sin_zero[8]; struct in_addr unsigned long s_addr; ; typedef struct in_addr union S_un; struct unsigned char s_b1, s_b2, s_b3, s_b4; S_un_b; struct unsigned short s_w1, s_w2; S_un_w; unsigned long S_addr; IN_ADDR; 参数 sin_family: 指代协议簇, 在 Socket 编程中只能是 AF_INET 参数 sin_port: 存储端口号 ( 使用网络字节顺序 ) 参数 sin_addr: 存储 IP 地址, 使用 in_addr 这个数据结构 参数 sin_zero: 为了让 sockaddr 与 sockaddr_in 两个数据结构保持大小相同而保留的空字 节, 一般为 0 参数 s_addr: 按照网络字节顺序存储 IP 地址 htons 和 htonl 函数 这两个函数都是用于将主机字节顺序与网络字节顺序进行转换的 主机字节就是计算机 内存里存放的整数或浮点数的方式, 字节在内存中的存放, 低字节在前, 高字节在后排列 网络字节就是在网络上描述整数或浮点数的字节发送顺序 ( 哪个字节被先发出去, 哪个字节 后发出去 ) 网络字节通常先传递高字节, 再传递低字节 为了数据的一致性, 就要把本地 的数据转换成网络上使用的格式, 然后发送出去, 接收的时候也是一样的, 经过转换然后才 去使用这些数据 htons 函数 : 将 16 位主机字节转换为网络字节, 使用函数 htons(), 定义如下 : u_short htons(u_short hostshort); 参数 hostshort: 表示主机字节顺序的数字, 函数返回网络字节顺序的数字 htonl 函数 : 将主机的 unsigned long 值转换为网络字节顺序 (32 位 ), 使用函数 htonl(), 其定义如下 : u_long htonl(u_long hostlong); 参数 hostlong: 表示主机字节顺序的数字, 函数返回一个网络字节顺序的数字 socket 和 closesocket 函数 socket 函数 : 初始化 WinSock 的动态连接库后, 需要在服务器端建立一个监听的套接字, 为此可以调 用 socket() 函数来建立这个监听的套接字, 并定义此套接字所使用的通信协议 在客户端也 第 2 章扫描可控计算机 21
8 22 Visual C++ 网络编程技术 同样调用 socket() 来建立一个 TCP 或 UDP 套接字 其函数原型如下 : SOCKET socket( int af, int type, int protocol ) 参数 af: 说明套接字要使用的协议地址簇, 目前只提供 AF_INET 表示使用互联网协议 (IP) 地址 参数 type : 描述套接字的类型, 只能是 SOCK_STREAM SOCK_DGRAM SOCK_RAW 三个协议类型中的一个, 分别表示流套接字 数据报套接字和原始套接字 参数 protocol: 该套接字使用的特定通信协定 ( 如果使用者不指定则设为 0) closesocket 函数 : 关闭服务器和客户端的通信连接是很简单的, 这一过程可以由服务器或客户机的任一端 启动, 只要调用 closesocket() 就可以了, 而要关闭服务器端监听状态的套接字, 同样也是利 用此函数, 该函数调用成功返回 0, 否则返回 SOCKET_ERROR 其函数原型如下 : int t closesocket(socket s); 参数 s: 为要关闭的套接字识别码 bind 函数 建立套接字后, 需要为服务器端定义的这个监听的套接字指定一个地址及监听端口 (Port), 这样客户端才知道要连接哪一个地址的哪个端口, 为此需要调用 bind() 函数, 该函 数调用成功返回 0, 否则返回 SOCKET ERROR int bind( SOCKET s, const Struct sockaddr FAR *name, int namelen ); 参数 s: 表示未绑定的套接字的对象名, 它是 socket() 函数调用成功时返回的值 参数 name: 套接字的地址值, 是一个与指定协议有关的地址结构指针, 这个地址必须 是执行这个程序所在机器的 IP 地址, 在 WinSock 中使用 sockaddr_in 结构指定 IP 地址和端 口号,sockaddr_in 结构的具体定义前面已经介绍 参数 namelen: 地址参数 name 的长度 listen 函数 listen 函数被 TCP 服务器端使用, 通知协议内核用户进程准备接受接口的连接请求, 指 定了套接字等待的连接数限制值 若成功执行完毕, 则函数返回 0 ; 否则返回 SOCKET_ERROR 函数原型如下 : int listen(socket s, int backlog); 参数 s: 已绑定但尚未连接的套接字句柄, 也是由 socket() 函数创建的套接字句柄 参数 backlog: 待处理的连接队列的最大长度 当连接的客户数大于这个最大长度并且 服务进程没有来得及处理, 则多出的连接请求会失败 目前允许的最大值为 5 accept 函数 对于服务器编程中最重要的一步等待并接受客户的连接,accept 函数就完成了这个功 能 它从内核中取出已经建立的客户连接, 然后把这个已经建立的连接返回给用户程序, 此 时用户程序就可以与自己的客户进行点到点的通信了 接收套接字使用函数 accept(), 其函数原型如下 : int accept(socket s, struct sockaddr FAR* addr, int FAR* addrlen); 该函数返回一个新的套接字, 该套接字可以用来与对方进行通信, 而原先的套接字还是 处于监听状态
9 参数 s: 表示处于监听模式的套接字句柄 参数 addr:sockaddr IN 对象的地址 参数 addrlen: 表示 addr 参数的长度 这个函数取出被搁置的连接队列中的第一个连接请求 函数执行后第 2 个参数和第 3 个 参数指向的变量会被函数设置为客户 IPv4 地址信息和该信息的长度 在调用 accept() 函数前 应该先调用 listen() 如果这个函数出错, 会返回 INVALID_SOCKET accept() 用于面向连接 服务, 参数 addr 和 addrlen 存放客户端的地址信息 调用前, 参数 addr 指向一个初始值为空 的地址结构, 而 addrlen 的初始值为 0; 调用后, 服务器等待从编号为 s 的套接字上接收客户 连接请求, 而连接请求是由客户端的 connect() 调用发出的 当有连接请求到达时,accept() 调用将连接队列上的第一个客户端套接字地址及长度放入 addr 利 addrlen, 并创建一个与 s 有相同特性的新套接字句柄 send 和 recv 函数 send 函数 : 在面向连接的服务套接字中, 不论是客户还是服务器应用程序都使用 send 函数发送数 据, 如果函数成功执行, 返回值是发送的字节数, 否则返回 SOCKET_ERROR 其定义如下 : int send( SOCKET s, const char FAR *buf, int len, int flags ); 参数 s: 表示已连接的本地套接字描述符 参数 buf: 表示要发送的缓冲区数据 参数 len: 表示缓冲区的长度 参数 flags: 表示标志类型, 可以为 0,MSG_DONTROUTE,MSG_OOB recv 函数 : 在面向连接的服务套接字中, 不论是客户还是服务器应用程序都用 recv 函数从 TCP 连 接的另一端接收数据 当应用程序调用 recv 函数时,recv 先等待 s 的发送缓冲中的数据被协 议传送完毕, 如果协议在传送 s 的发送缓冲中的数据时出现网络错误, 那么 recv 函数返回 SOCKET_ERROR, 如果 s 的发送缓冲中没有数据或者数据被协议成功发送完毕后,recv 先 检查套接字 s 的接收缓冲区, 如果 s 接收缓冲区中没有数据或者协议正在接收数据, 那么 recv 就一直等待, 直到协议把数据接收完毕 当协议把数据接收完毕,recv 函数就把 s 的接 收缓冲区中的数据 copy 到 buf 中 ( 注意协议接收到的数据可能大于 buf 的长度, 所以在这种 情况下要调用几次 recv 函数才能把 s 的接收缓冲区中的数据 copy 完 recv 函数仅仅是 copy 数据, 真正的接收数据是协议来完成的 ),recv 函数返回其实际 copy 的字节数 如果 recv 函 数在 copy 时出错, 那么它返回 SOCKET_ERROR; 如果 recv 函数在等待协议接收数据时网 络中断了, 那么它返回 0 其函数原型如下 : int recv( SOCKET s, char FAR *buf, int len, int flags); 参数 s: 接收端套接字描述符 参数 buf: 指明一个缓冲区, 该缓冲区用来存放 recv 函数接收到的数据 参数 len:buf 的长度 参数 flags: 表示标志, 可以是 0,MSG_PEEK,MSG_OOB 一般置 0 memset 函数 第 2 章扫描可控计算机 23
10 24 Visual C++ 网络编程技术 memset() 函数功能是一字节一字节地把整个数组设置为一个指定的值 其函数原型如下 : void *memset(void*,int,unsigned); 该函数在 mem.h 头文件中声明, 它把数组的起始地址作为其第一个参数, 第二个参数 是设置数组每个字节的值, 第三个参数是数组的长度 ( 字节数, 不是元素个数 ) memset() 函数常用于内存空间初始化 如 : char str[100]; memset(str,0,100); strcpy 函数 strcpy 函数提供了字符串的复制, 即 strcpy 只用于字符串复制, 并且它不仅复制字符串 内容之外, 还会复制字符串的结束符 其函数原型如下 : char *strcpy(char *strdest, const char *strsrc) 客户端程序代码清单 : #include "stdio.h" #include <winsock2.h> #pragma comment(lib,"ws2_32.lib") int main(int argc, char* argv[]) // 初始化 WinSock 为 2.0 版本 WSADATA wsadata; int ret; if((ret=wsastartup(makeword(2,2),&wsadata))!=0) printf(" 初始化 WinSock 出错!"); // 定义客户端 socket 变量 SOCKET clientsocket; // 定义服务器端地址信息 struct sockaddr_in serv; // 定义一个长度为 1024 的字符数组, 用来存放发送和接收的数据 char buf[1024]; // 设置服务器地址信息 serv.sin_family=af_inet; serv.sin_port=htons(8888); // 设置需连接的服务器的监听端口 ( 必须与服务器端绑定的监听端口一致 ) serv.sin_addr.s_addr=inet_addr(" "); // 建立客户端 socket clientsocket=socket(af_inet,sock_stream,0); if(clientsocket==invalid_socket) printf(" 建立 socket 出错!"); // 此处应设置为服务器端的 IP 地址
11 // 请求与服务器建立 TCP 连接 if(connect(clientsocket,(struct sockaddr *)&serv,sizeof(serv))==invalid_socket) printf(" 请求建立连接出错!"); printf(" 已经成功与服务器建立连接...\n"); // 发送数据给服务器 memset(buf,0,sizeof(buf)); strcpy(buf,"are You Ready?"); ret=send(clientsocket,buf,sizeof(buf),0); if(ret==socket_error) printf(" 发送数据出错 "); printf(" 发送数据给服务器...\n"); // 接收服务器发回的数据 memset(buf,0,sizeof(buf)); ret=recv(clientsocket,buf,sizeof(buf),0); if(ret==0) 代码解析 : printf(" 接收到服务器回复信息内容 :"); printf(buf); printf("\n"); // 关闭 socket closesocket(clientsocket); WSACleanup(); connect connect 函数的功能就是完成面向连接的协议的连接过程 面向连接的协议, 在建立连 接的时候总会有一方先发送数据, 那么谁调用了 connect 谁就是先发送数据的一方 connect 函数的功能是完成一个有连接协议的连接过程 如果函数调用没有错误发生, 返回值为 0, 否则返回值 SOCKET_ERROR 它的函数原型如下 : int connect(socket s, const struct sockaddr FAR* name, int namelen); 参数 s: 表示是将要和服务器建立连接的套接字句柄 参数 name: 服务器的地址结构 参数 namelen: 地址名字 name 的长度 在面向连接的协议中, 该调用导致本地系统和外部系统之间建立实际连接 第 2 章扫描可控计算机 25
12 26 Visual C++ 网络编程技术 使用 MFC 的 CSocket 类实现微软的 MFC 把复杂的 WinSock API 函数封装到类中, 这使得编写网络应用程序更容易 MFC 中的 CAsyncSocket 类逐个封装了 WinSock API, 为高级网络程序员提供了更加有力而灵活的方法 为了给程序员提供更方便的接口以自动处理这些任务,MFC 给出了 CSocket 类 CSocket 类是由 CAsyncSocket 继承而来的, 事实上, 在 MFC 中 CAsyncSocket 逐个封装了 WinSock API, 每个 CAsyncSocket 对象代表一个 Windows Socket 对象, 使用 CAsyncSocket 类要求程序员对网络编程较为熟悉 相比起来,CSocket 类是 CAsyncSocket 的派生类, 继承了它封装的 WinSock API 一个 CSocket 对象代表了一个比 CAsyncSocket 对象更高层次的 Windows Socket 的抽象,CSocket 类与 CSocketFile 类和 CArchive 类一起工作来发送和接收数据, 因此使用它更加容易 CSocket 对象提供阻塞模式, 因为阻塞功能对于 CArchive 的同步操作是至关重要的 在这里有必要对阻塞的概念作一解释 : 一个 Socket 可以处于 阻塞模式 或 非阻塞模式, 当一个套接字处于阻塞模式 ( 即同步操作 ) 时, 它的阻塞函数直到操作完成才会返回控制权, 之所以称为阻塞是因为此套接字的阻塞函数在完成操作返回之前什么也不能做 如果一个 Socket 处于非阻塞模式 ( 即异步操作 ), 则会被调用函数立即返回 在 Win32 环境下, 如果要使用具有阻塞性质的套接字, 应该放在独立的工作线程中处理, 利用多线程的方法使阻塞不至于干扰其他线程, 也不会把 CPU 时间浪费在阻塞上 多线程的方法既可以使程序员享受 CSocket 带来的简化编程的便利, 也不会影响用户界面对用户的反应 关于多线程编程, 在后面的章节中会详细讲解和示范 使用 CSocket 类的编程过程如下 : (1) 构造一个 CSocket 对象 (2) 使用这个对象的 Create() 成员函数产生一个 Socket 对象 在客户方程序中, 除非需要数据报套接字,Create() 函数一般情况下应该使用默认参数 而对于服务方程序, 必须在调用 Create 时指定一个端口 (3) 如果是客户方套接字, 则调用 Connect() 函数与服务方套接字连接 ; 如果是服务方套接字, 则调用 Listen() 开始监听来自客户方的连接请求, 收到连接请求后, 调用 Accept() 函数接受请求, 建立连接 请注意 Accept() 成员函数需要一个新的并且为空的 CSocket 对象作为它的参数 (4) 连接成功建立后, 可以使用 Receive() 和 Send() 函数进行数据发送和接收工作 (5) 通信结束后, 使用 Close() 函数销毁 CSocket 对象 使用 CSocket 进行通信编程的流程图如图 2-6 所示 使用 MFC 提供的 CSocket 类可以使我们的通信程序变得更加简单, 为了得到 MFC 的支持, 需要在创建工程时指明创建的是 MFC AppWizard[exe] 程序, 在 下一步 的选项中, 选择要创建的应用程序类型是 基本对话框, 在 下一步 的选项中, 可以选择 希望支持 Windows Sockets, 如果选择了此选项, 则系统会自动初始化 WinSock, 如果没有选择, 则需要在代码中自己进行初始化 工程创建完后, 有一个简单的对话框界面, 可以根据需要进行界面的修改 服务器端界面和客户端界面经过修改后如图 2-7 和图 2-9 所示
13 图 2-6 使用 CSocket 类实现的面向连接的套接字通信过程 图 2-7 服务器端程序界面 服务器端源程序 : 在写入代码的文件头, 引入所需头文件 :#include <afxsock.h>, 修改界面如图 2-7 后, 双击 启动服务器程序 按钮, 添加按钮的消息处理函数, 在该函数里添加代码如下 : // 初始化 WinSock 为 2.0 版本 WSADATA wsadata; if((wsastartup(makeword(2,2),&wsadata))!=0) MessageBox(" 初始化 WinSock 出错!",NULL,MB_OK); // 定义两个 socket 变量, 一个用来监听, 一个用来建立连接和提供服务 CSocket listensocket,acceptsocket; 第 2 章扫描可控计算机 27
14 28 Visual C++ 网络编程技术 int ret; // 创建监听 socket ret=listensocket.create(8888); if(ret==0) MessageBox(" 建立 socket 出错!",NULL,MB_OK); // 开始监听 ret=listensocket.listen(5); if(ret==0) MessageBox(" 监听出错 ",NULL,MB_OK); // 等待客户连接请求, 如有连接请求到来, 则用 acceptsocket 与其建立连接, 进行通信 ret=listensocket.accept(acceptsocket,null,null); if(ret==0) MessageBox(" 建立连接出错 ",NULL,MB_OK); // 接收数据 char buf[1024];// 准备一个长度为 1024 的字符数组, 用来接收数据 ret=acceptsocket.receive(buf,sizeof(buf),0); if(ret==0) CString str=" 从客户端发来的信息 :"; str=str+buf; MessageBox(str," 通信内容 ",MB_OK); // 发送数据 memset(buf,0,sizeof(buf)); strcpy(buf,"ok"); ret=acceptsocket.send(buf,sizeof(buf),0); if(ret==socket_error) MessageBox(" 发送数据出错 ",NULL,MB_OK); // 关闭 socket acceptsocket.close(); listensocket.close(); WSACleanup(); 代码解析 : #include <afxsock.h> 头文件 afxsock.h 中包含 CAsyncSocket 和 CSocket 类定义 如果使用这些类或从这些类
15 派生的任何类, 必须确保在项目中包含 afxsock.h 文件 Create 函数 构造套接字对象后调用 Create() 成员函数创建 Socket 句柄, 并调用 Bind() 成员函数将其与 指定的地址绑定 如果该函数调用成功, 则返回非 0 值, 否则返回 0 值 其函数原型如下 : BOOL Create(UINT nsocketport = 0, int nsockettype = SOCK_STREAM, long levent = FD_READ FD_WRITE FD_OOB FD_ACCEPT FD_CONNECT FD_CLOSE, LPCTSTR lpszsocketaddress = NULL); 参数 nsocketport: 与套接字一起使用的端口号, 默认值为 0, 表示自动选择端口号 参数 nsockettype: 指定要创建的套接字类型, 默认为流式套接字 参数 levent: 指定感兴趣的网络事件的掩码位, 网络事件见表 2-1 参数 lpszsocketaddress: 指定套接字的网络地址 表 2-1 网络事件类型 事件标记 事件内容 FD_READ FD_WRITE FD_OOB FD_ACCEPT FD_CONNECT FD_CLOSE 接收读准备好的通知接收写准备好的通知接收带外数据到达的通知接收等待连接成功的通知接收已连接好的通知接收套接字关闭的通知 型如下 : Listen 函数 该函数用于侦听连接请求, 如果函数执行成功则返回非 0 值, 否则返回 0 值 其函数原 BOOL Listen(int nconnectionbacklog = 5); 参数 nconnectionbacklog: 指定连接请求队列的最大连接数目, 默认为 5 Accept 函数 该函数接受一个套接字的连接请求, 从连接请求队列中取出第一个连接, 并创建一个与 这个套接字具有相同属性的套接字, 并与第一个参数 (Socket 对象 ) 相关联, 原始的套接字依 然保持打开并且侦听 如果函数执行成功则返回非 0 值, 否则返回 0 值 其函数原型如下 : virtual BOOL Accept (CAsyncSocket & rconnectedsocket, SOCKADDR* lpsockaddr = NULL, int* lpsockaddrlen = NULL) ; 参数 rconnectedsocket: 用来进行连接的新套接字的引用 参数 lpslpsockaddr: 用来返回发送连接请求的套接字地址的 SOCKADDR 结构指针 参数 lpsockaddrlen: 指向 psockaddr 结构中地址的字节长度的指针 Receive 函数 该函数从一个面向连接的流或者面向无连接的数据报套接字接收数据 如果函数调用成 功, 则返回所接收到的字节数 ; 如果连接被关闭, 则返回 0; 如果函数调用失败, 则返回 SOCKET_ERROR 其函数原型如下 : virtual int Receive(void* lpbuf, int nbuflen, int nflags = 0); 第 2 章扫描可控计算机 29
16 30 Visual C++ 网络编程技术 认为 0 参数 lpbuf: 接收数据的缓冲区 参数 nbuflen: 缓冲区的字节节长度 参数 nflags: 用来表示函数的实现, 值为 MSG_OOB 和 MSG_PEEK 项的组合, 通常默 Send 函数 该函数通过数据报或数据流向对方套接字发送数据, 如果函数成功调用, 则返回发送的 字节总数, 否则返回 SOCKET_ERROR 其函数原型如下 : virtual int Send(const void* lpbuf, int nbuflen, int nflags = 0); 参数 lpbuf: 要发送的数据的缓冲区地址 参数 nbuflen: 为 lpbuf 缓冲区的字节长度 参数 nflags: 指定函数的调用标志, 其取值为 MSG_DONTROUTE 和 MSG_OOB 的组 合, 默认值为 0 如下 : Close 函数 该函数用来关闭套接字并释放 Socket 描述符, 其函数原型如下 : Virtual void Close (); MessageBox 函数 这个函数可以在 VC 里面显示一个标准对话框, 通常用来弹出提示对话框 其函数原型 int MessageBox(HWND hwnd, LPCTSTR lptext, LPCTSTR lpcaption, UINT, utype); 参数 hwnd: 父窗口的句柄 参数 lptext: 对话框的内容 参数 lpcaption: 对话框的标题 参数 utype: 窗口的风格 该函数为窗口提供了多种风格, 具体标示见表 2-2 表 2-2 弹出对话框窗口风格 风格标示 风格 MB_DEFBUTTON1 MB_DEFBUTTON2 MB_DEFBUTTON3 MB_ICONEXCLAMATION MB_ICONQUESTION MB_ICONSTOP MB_ YESNOCANCEL MB_OK MB_OKCANCEL MB_RETRYCANCEL 缺省按钮为第一个按钮缺省按钮为第二个按钮缺省按钮为第三个按钮显示图标为惊叹号显示图标为问号显示图标为红叉叉显示是 否 取消按钮只显示确定按钮显示确定和取消按钮显示重试和取消按钮 表 2-3 用户针对对话框作了相应选择后, 根据用户选择的不同, 系统有不同的返回值, 见
17 表 2-3 对话框返回值 返回值 含义 IDABOUT IDRETRY IDIGNORE IDOK IDCANSEL IDYES IDNO 按下了终止按钮按下了重试按钮按下了忽略按钮按下了确定按钮按下了取消按钮按下了是按钮按下了否按钮 例如 : 要显示一个图标为问号, 按钮为 是 否 取消, 并且默认按钮为 否, 标题为 问题, 内容为 你明白了吗? 的对话框, 并且还要求如果单击了 是 按钮, 则给 a 赋值为 1, 那么语句则为 : if(messagebox(" 你明白了吗?", " 问题 ", MB_YESNOCANCEL MB_DEFBUTTON2 MB_ICONQUESTION ) == IDYES) a = 1; 该语句执行后弹出的对话框如图 2-8 所示 接下来看看客户端程序怎样实现, 界面如图 2-9 所示 客户端源程序 : 图 2-8 弹出的对话框图 2-9 客户端程序界面 在写入代码的文件头, 引入所需头文件 :#include <afxsock.h>, 修改界面如图 2-9 后, 双击 连接服务器 按钮, 添加按钮的消息处理函数, 在该函数里添加代码如下 : // 初始化 WinSock 为 2.0 版本 WSADATA wsadata; if((wsastartup(makeword(2,2),&wsadata))!=0) MessageBox(" 初始化 WinSock 出错!",NULL,MB_OK); // 定义客户端 socket 变量 CSocket clientsocket; int ret; // 建立客户端 socket ret=clientsocket.create(); if(ret==0) 第 2 章扫描可控计算机 31
18 32 Visual C++ 网络编程技术 MessageBox(" 建立 socket 出错!",NULL,MB_OK); // 定义一个长度为 1024 的字符数组, 用来存放发送和接收的数据 char buf[1024]; // 请求与服务器建立 TCP 连接, 在参数中指明服务器的 IP 地址和监听端口号 ret=clientsocket.connect(" ",8888); if(ret==0) MessageBox(" 请求建立连接出错!",NULL,MB_OK); // 发送数据给服务器 memset(buf,0,sizeof(buf)); strcpy(buf,"are You Ready?"); ret=clientsocket.send(buf,sizeof(buf),0); if(ret==0) MessageBox(" 发送数据出错 ",NULL,MB_OK); // 接收服务器发回的数据 memset(buf,0,sizeof(buf)); ret=clientsocket.receive(buf,sizeof(buf),0); if(ret==0) CString str=" 从服务器端发回的信息 :"; str=str+buf; MessageBox(str," 通信内容 ",MB_OK); // 关闭 socket clientsocket.close(); WSACleanup(); 代码解析 : Connect 函数 该函数用于未连接的数据流或数据报套接字建立连接 如果函数调用成功则返回非 0 值, 否则返回 0 值 其函数原型如下 : BOOL Connect (LPCTSTR lpszhostaddress, UINT nhostport); 参数 lpszhostaddress: 用于要连接的服务器网络地址 参数 nhostport: 指定套接字应用程序使用的端口号 BOOL Connect (const SOCKADDR* lpsockaddr, int nsockaddrlen); 参数 lpsockaddr: 指向 SOCKADDR 结构的指针 参数 nsockaddrlen:lpsockaddr 指针中地址的字节长度
19 2.3 扩展核心程序 经过分析, 确定应该首先建立两个应用程序, 一个 teacher 和一个 student student 程序应首先启动,teacher 程序能够主动向所有 student 程序发出连接请求, 能够成功建立连接的就是可控学生机, 把其 IP 地址显示在 teacher 程序界面上 使用 MFC 的 CSocket 类编程实现首先创建工程 student, 类型是 MFC AppWizard[exe], 在 下一步 的选项中, 选择要创建的应用程序类型是 基本对话框, 在 下一步 的选项中, 选择 希望支持 Windows Sockets 选项, 然后完成工程的创建 将程序界面修改如图 2-10 所示 图 2-10 student 程序界面 界面上共有两种控件, 左侧是两个按钮控件, 右侧是一个静态文本控件 双击 启动学 生机 按钮, 添加按钮消息处理函数, 源代码如下 : CSocket listensocket; CSocket datasocket; int ret; ret=listensocket.create(8888); // 创建一个 socket, 指定监听端口 8888 if(ret==0) MessageBox(" 创建 socket 出错 ",NULL,MB_OK); ret=listensocket.listen(5); // 开始监听 if(ret==0) MessageBox(" 监听出错 ",NULL,MB_OK); ret=listensocket.accept(datasocket,null,null); if(ret==0) MessageBox(" 建立连接出错 ",NULL,MB_OK); char strrev[256]=0; datasocket.receive(strrev,256,0); // 接受客户发送的消息 // 当接到客户请求时, 建立连接 第 2 章扫描可控计算机 33
20 34 Visual C++ 网络编程技术 CString strmeg=strrev; if(!strmeg.compare("ok")) CString strsend="ok"; datasocket.send(strsend,strsend.getlength(),0); // 发送消息给客户 listensocket.close(); datasocket.close(); 接下来, 创建工程 teacher, 类型是 MFC AppWizard[exe], 在 下一步 的选项中, 选 择要创建的应用程序类型是 基本对话框, 在 下一步 的选项中, 选择 希望支持 Windows Sockets 选项, 然后完成工程的创建 将程序界面修改如图 2-11 所示 图 2-11 teacher 程序界面 界面上涉及几种 MFC 控件, 显示文字内容的是静态文本控件, 允许输入 IP 地址的两个 控件是编辑框, 右侧 开始扫描 是按钮, 下面用于显示可控计算机列表的是列表框控件 因为界面开发不是本教材的重点, 所以只简单介绍用到的控件 首先把 teacher 程序的界面按照图 2-11 进行修改, 然后按照要求修改几个控件的 ID( 选 中要修改的控件, 鼠标右键单击, 选择属性项, 在属性对话框中修改 ID 值 ): 输入开始 IP 的编辑框控件 ID 修改为 :IDC_START; 输入结束 IP 的编辑框控件 ID 修改为 :IDC_END; 显示可控计算机列表的列表框控件 ID 修改为 :IDC_SHOW; 开始扫描 按钮控件 ID 修改 为 :IDC_SERCH 然后为上面三个控件添加关联的成员变量 添加方法 : 单击 查看 菜单, 选择 建立 类向导, 在 MFC ClassWizard 对话框中, 选择 Member Variables 选项卡, 为 IDC_START 添 加成员变量 m_start, 类型为 CString; 为 IDC_END 添加成员变量 m_end, 类型为 CString; 为 IDC_SHOW 添加成员变量 m_show, 类型为 CListBox 当需要从控件里读出数据或者在 控件里显示数据时, 都需要用到控件关联的成员变量 双击 开始扫描 按钮, 添加按钮消息处理函数, 在该函数中写入源代码 : // 获取要搜索的 IP 范围 UpdateData(true);// 使用户输入的两个 IP 地址保存到编辑框对应的成员变量中 // 对获取到的 IP 地址范围进行解析, 取出 IP 地址的最后一段, 用于循环使用 CString iphead=m_start.left(m_start.reversefind('.'));
21 int ip1,ip2; //ip 地址循环的起始和结束值 ip1=atoi(m_start.right(m_start.getlength()-m_start.reversefind('.')-1)); ip2=atoi(m_end.right(m_end.getlength()-m_end.reversefind('.')-1)); //Socket 连接 CSocket clientsocket; clientsocket.create();// 创建一个 socket char strrev[256]=0; for(int i=ip1;i<=ip2;i++) CString tp; tp.format("%d",i); CString ip = iphead + "." + tp; // 参数是要连接服务器的 IP 地址和服务器的监听端口 int ret = clientsocket.connect(ip,8888); if(ret==0) continue; CString msg = "ok"; clientsocket.send(msg,msg.getlength()); // 发送消息给服务器 memset(strrev,0,256); clientsocket.receive(strrev,256,0);// 接收服务器的消息 msg=strrev; ret = msg.compare("ok"); if(ret==0) // 添加到列表中 m_show.addstring(ip + " 机器已运行 "); clientsocket.close(); 思考 : 进一步扩展, 如果希望程序可以由用户自己添加学生机, 如何实现? 使用 WinSock 编程实现 修改上面的 CSocket 通信程序, 使用 WinSock 编程实现相同的功能, 界面开发部分完全 相同, 只需针对按钮消息相应函数中的代码进行修改, 修改后的代码如下 : student 源程序 : // 定义两个 socket 变量, 一个用来监听, 一个用来建立连接和提供服务 SOCKET listensocket; SOCKET datasocket; BOOL ret; // 设置服务器 客户的地址和端口 struct sockaddr_in serv,cliet; // 创建监听 socket listensocket=socket(af_inet,sock_stream,0); if(listensocket==invalid_socket) MessageBox(" 建立 socket 出错 ",NULL,MB_OK); 第 2 章扫描可控计算机 35
22 36 Visual C++ 网络编程技术 // 设置服务器地址信息 serv.sin_family=af_inet; serv.sin_port=htons(8888);// 设置监听端口是 8888 serv.sin_addr.s_addr=htonl(inaddr_any); // 将监听 socket 与服务器地址绑定 if(bind(listensocket,(lpsockaddr)&serv,sizeof(serv))==socket_error) MessageBox(" 绑定出错 ",NULL,MB_OK); // 开始监听 if(listen(listensocket,5)==socket_error) MessageBox(" 监听出错 ",NULL,MB_OK); // 等待客户连接请求, 如有连接请求到来, 则用 acceptsocket 与其建立连接, 进行通信 int len=sizeof(cliet); datasocket=accept(listensocket,(struct sockaddr *)&cliet,&len); if(datasocket==invalid_socket) MessageBox(" 建立连接出错 ",NULL,MB_OK); char strrev[256]=0; ret=recv(datasocket,strrev,sizeof(strrev),0); if(ret==0) CString strmeg=strrev; if(!strmeg.compare("ok")) memset(strrev,0,sizeof(strrev)); strcpy(strrev,"ok"); ret=send(datasocket,strrev,sizeof(strrev),0); if(ret==socket_error) closesocket(datasocket); closesocket(listensocket); teacher 源程序 : // 获取要搜索的 IP 范围 UpdateData(true); // 对获取到的 IP 地址范围进行解析, 取出 IP 地址的最后一段, 用于循环使用 CString iphead=m_start.left(m_start.reversefind('.'));
23 int ip1,ip2; //ip 地址循环的起始和结束值 ip1=atoi(m_start.right(m_start.getlength()-m_start.reversefind('.')-1)); ip2=atoi(m_end.right(m_end.getlength()-m_end.reversefind('.')-1)); SOCKET clientsocket; // 定义服务器端地址信息 struct sockaddr_in serv; char strrev[256]=0; CString tp,ip; for(int i=ip1;i<=ip2;i++) tp.format("%d",i); ip = iphead + "." + tp; // 设置服务器地址信息 serv.sin_family=af_inet; serv.sin_port=htons(8888); // 设置需连接的服务器的监听端口 ( 必须与服务器端绑定的监听端口一致 ) serv.sin_addr.s_addr=inet_addr(ip);// 此处应设置为服务器端的 IP 地址 // 建立客户端 socket clientsocket=socket(af_inet,sock_stream,0); if(clientsocket==invalid_socket) MessageBox(" 建立 socket 出错!",NULL,MB_OK); // 请求与服务器建立 TCP 连接 if(connect(clientsocket,(struct sockaddr *)&serv,sizeof(serv))==invalid_socket) continue; memset(strrev,0,sizeof(strrev)); strcpy(strrev,"ok"); send(clientsocket,strrev,sizeof(strrev),0);// 发送消息给服务器 memset(strrev,0,sizeof(strrev)); recv(clientsocket,strrev,sizeof(strrev),0);;// 接收服务器的消息 CString msg=strrev; int ret = msg.compare("ok"); if(ret==0) // 添加到列表中 m_show.addstring(ip + " 机器已运行 "); closesocket(clientsocket); 第 2 章扫描可控计算机 37
24 38 Visual C++ 网络编程技术 2.4 知识扩展 澄清一些概念 Socket 在英文屮是 插座 的意思, 它的设计者实际上是暗指电话插座 因为在 Socket 环境下编程很像是模拟打电话,Internet 的 IP 就是电话号码, 要打电话, 需要电话插座, 在程序中就是向系统申请一个 Socket, 以后两台机器上的程序 交谈 都是通过这个 Socket 来进行的 对程序员来说, 也可以把 Socket 看成一个文件指针, 只要向指针所指的文件读写数据, 就可以实现双向通信 利用 Socket 进行通信, 有两种主要的方式 第一种是面向连接的流方式 顾名思义, 在这种方式下, 两个通信的应用程序之间先要建立一种连接链路, 其过程好像在打电话 一台计算机 ( 电话 ) 要想和另一台计算机 ( 电话 ) 进行数据传输 ( 通话 ), 须首先获得一条链路, 只有确定了这条通路之后, 数据 ( 通话 ) 才能被正确接收和发送, 这种方式对应的是 TCP(Transport Control Protocol) 第二种叫做无连接的数据报文方式, 这时两台计算机像是把数据放在一个信封里, 通过网络寄给对方, 信在传送的过程中有可能会残缺不全, 而且后发出的信也有可能会先收到, 它对应的是 UDP(User Datagram Protocol) 流方式的特点是通信可靠, 对数据有校验和重发的机制, 通常用来做数据文件的传输, 如 FTP Telnet 等, 数据报文方式由于取消了重发校验机制, 能够达到较高的通信速率, 可用于对数据可靠性要求不高的通信, 如实时的语音 图像转送和广播消息等 在 ISO 的 OSI 网络七层协议中,WinSock 主要负责控制数据的输入和输出, 也就是传输层和网络层 WinSock 屏蔽了数据链路层和物理层, 它的出现给 Windows 下的网络编程带来了巨大的变化 套接字有同步阻塞方式和异步非阻塞方式两种使用方法 同步和异步往往都是针对一个函数来说的, 同步 就是函数直到其要执行的功能全部完成时才返回, 而 异步 则是函数仅仅做一些简单的工作, 然后马上返回, 所要实现的功能留给别的线程或者消息循环去完成 阻塞方式的套接字简单 易用, 但效率低 相比之下, 异步套接字使用复杂, 但效率很高 本章实例使用的是阻塞方式 WinSock 编程原理 Windows Sockets API 是 Windows 下的网络应用程序接口, 用于网络通信 API 函数有 1.1 版和 2.0 版, 称为 WinSockl 和 WinSock2, 通过前缀 WSA 区分 2.0 版有良好的向后兼容性, 任何使用 1.1 版的源代码 二进制文件和应用程序都可以不加修改地在 2.0 规范下使用 现在基本上都使用 2.0 版本进行开发, 它主要是为了适应近年来网络技术的迅猛发展, 特别是多媒体网络技术迅速发展的需要, 通过制定 Windows Sockets2 规范来提供一个与协议无关的网络传输接口 Windows Sockets 使用套接字进行编程, 套接字编程是面向客户端 / 服务器模型而设计的, 因此系统中需要客户端和服务器两个不同类型的进程, 根据连接类型的不同, 对于面向连接的 TCP 服务和无连接的 UDP 服务, 服务器分别采取不同的处理操作来对客户提供服务
25 对于面向连接的 TCP 服务, 服务器需要等待客户端向其提出的建立连接的申请, 一旦接收到客户端的连接请求, 服务器返回一个新的套接字描述符, 通过该描述符调用数据传输函数即可与客户端进行数据的收发 对于无连接的 UDP 服务, 服务器通常是面向事务处理的, 服务器和客户端在传输数据之前不需要进行连接的申请和建立, 数据传输结束后, 直接关闭套接字即可完成一次通信 WinSock 中的主要函数如下 : WinSock 的打开 WSAStartup() 服务器建立套接字 socket() 服务器绑定端口 bind() 客户端提出连接申请 connect() 服务器端接受客户端的连接请求 accept() 数据的传送 send() 和 recv() 关闭套接字 closesocket() 关闭 WinSock WSACleanup() 这些函数的具体定义信息前面已经详细介绍了, 这里就不再赘述 MFC 网络编程 MFC 中有两个主要的网络编程类 :CAsyncSocket 类和 CSocket 类 CAsyncSocket 类用面向对象的方法封装了 WinSock,CSocket 类是 CAsyncSocket 类的子类 这两个类是 Visual C++ 环境中网络编程经常使用的两个类 1.CAsyncSocket 类介绍 CAsyncSocket 类对 Windows Sockets API 函数进行了封装, 它是从 CObject 类派生出来的 该类在非常低的级别上封装 Windows Sockets API CAsyncSocket 适合那些对网络通信细节很了解, 但希望利用回调的便利通知网络事件的程序员使用 如果想利用 Windows Sockets 方便地处理 MFC 应用程序中的多个网络协议, 而又不想放弃灵活性, 可以使用 CAsyncSocket, 但是程序员必须自己处理阻塞, 字节序的差异和 Unicode 多字节字符集 (MBCS) 的转换 CAsyncSocket 类的重要函数如下 : 构造套接字对象 Create() 接受套接字的连接请求 Accept() 将本机地址绑定到套接字 Bind() 建立连接 Connect() 监听连接请求 Listen() 发送数据 Send() 和 SendTo() 接受数据 Receive() 和 ReceiveFrom() 禁止发送接收数据 ShutDown() 关闭套接字 Close() 这些函数中大部分在前面程序代码详解里已经详细介绍过, 这里不再赘述 没有介绍的函数如下 : 将本机地址绑定到套接字 Bind() 第 2 章扫描可控计算机 39
26 40 Visual C++ 网络编程技术 该函数将本机地址绑定到套接宇, 在 Connect 或者 Listen 之前可以被调用 在能接受连 接请求前, 监听的服务器套接字必须选择一个端口号并调用 Bind 将本地名分配给未命名的 Windows 套接字, 使其知道自己的地址和端口号, 如果函数调用成功则返回非 0 值, 否则返 0 值 其函数原型如下 : BOOL Bind(UINT nsocketport, LPCTSTR lpszsocketaddress = NULL); 参数 nsocketport: 要绑定的套接字端口号 参数 lpszsocketaddress: 要绑定的套接字网络地址 BOOL Bind (const SOCKADDR* IpSockAddr, int nsockaddrlen); 参数 lpsockaddr: 指向 SOCKADDR 结构的指针 参数 nsockaddrlen:ipsockaddr 指针中地址的字节长度 发送数据 SendTo() 该函数与 Send() 类似, 也是通过数据报或者数据流套接字发送数据, 如果函数成功调 用, 则返回发送的字节总数, 否则返回 SOCKET_ERROR 其函数原型如下 : int SendTo (const void* lpbuf, int nbuflen, UINT nhostport, LPCTSTR lpszhostaddress = NULL, int nflags = 0); int SendTo(const void* lpbuf, int nbuflen, const SOCKADDR* lpsockaddr, int nsockaddrlen,int nflags = 0); 参数 lpbuf: 要发送的数据缓冲区地址 参数 nbuflen:lpbuf 缓冲区的字节长度 参数 nhostport: 套接字应用程序的端口号 参数 lpszhostaddress: 被连接的套接字的网络地址 参数 lpsockaddr:sockaddr 结构的指针 参数 nsockaddrlen: 指针所指向结构中的地址的字节长度的指针 参数 nflags: 函数的调用标志, 其取值为 MSG_DONTROUTE 和 MSG_OOB 的组合, 默认值为 0 接收数据 ReceiveFrom() 该函数从面向连接流或者无连接的数据报套接字接收数据, 并将源地址存放在 SOCKADDR 结构或者 rsockeladdress 中 如果函数调用成功, 则返回所读入的字节数, 如果 连接被关闭, 则返回 0, 如果函数调用失败, 则返回 SOCKET_ERROR 其函数原型如下 : int ReceiveFrom(void* lpbuf, int nbuflen, CString& rsocketaddress, UINT& rsocketport, int nflags = 0); int ReceiveFrom(void* lpbuf, int nbuflen, SOCKADDR* lpsockaddr, int*lpsockaddrlen, int nflags = 0); 参数 lpbuf: 接收数据的缓冲区 参数 nbuflen: 缓冲区的字节节长度 参数 rsocketaddress: 一个点分隔的字符串 IP 地址的 CString 对象的引用 参数 rsocketport: 端口号的 UINT 类型的引用 参数 lpsockaddr: 返回源地址的 SOCKADDR 结构指针 参数 lpsockaddrlen:lpsockaddr 的字节长度 参数 nflags: 用来表示函数的实现, 值为 MSG_OOB 和 MSG_PEEK 项的组合, 通常默
27 认为 0 禁止发送接收数据 ShutDown() 该函数用于禁止发送或者接收数据, 如果调用成功返回非 0 值, 否则返回 0 值 其函数 原型如下 : BOOL ShutDown (int nhow=sends) ; 参数 nhow: 不允许的操作, 可以取值为 SD_RECENE SD_SEND 或 SD_BOTH, 这三 个值的含义按照字面理解即可 2.CSocket 类介绍 CSocket 类是 CAsyncSocket 类的派生类, 它继承了 Windows Sockets API 封装函数 实 现了比 CAsyncSocket 类对 Windows Sockets 更高层的抽象 它与类 CSocketFile 和 CArchive 共同合作完成对发送数据 接收数据的管理,CSocket 类提供了对于同步操作 CArchive 对象 非常重要的阻塞功能, 使程序员在管理数据的发送和接收的工作变得简单 CSocket 类提供了阻塞的访问方式, 这对于 CArchive 类的同步操作是必需的, 其成员函 数如 Receive() Send() ReceiveFrom() SendToO 和 Accept() 不会像 WinSock 中的函数一样 返回错误, 这些函数会等待直到操作完成 CSocket 类的几个重要成员函数 : 创建套接字并将其同一个对象绑定起来 Create() 确定一个阻塞是否正在执行 IsBlocking() 其函数原型如下 : BOOL IsBlocking(); 如果套接字是阻塞状态返回非 0 值, 否则返回 0 值 返回一个指向 CSocket 对象的指针 FromHandle() 给定一个 Socket 句柄, 返回一个指向 CSocket 的指针, 如果没有 CSocket 对象绑定到这 个句柄上, 则该函数返回 NULL, 并且不创建临时的对象 其函数原型如下 : static CSocket* PASCAL FromHandle( SOCKET hsocket ); 参数 hsocket 为套接字句柄 把一个 Socket 句柄绑定到一个 CSocket 对象上 Attach() 该函数把一个 Socket 句柄绑定到一个 CSocket 对象上,SOCKET 句柄被保存到 CSocket 对象的成员变量 m_hsocket 中 如果调用成功返回非 0 值, 否则返回 0 值 其函数原型如下 : BOOL Attach(SOCKET hsocket) ; 参数 hsocket 为一个套接字的句柄 取消一个正在进行中的阻塞调用 CancelBlockingCall() 调用该函数, 原始的阻塞调用会立即终止并返回 WSAEINTR 错误 如果是阻塞的 Connect() 操作,Windows 套接字可以实现立即终止这个阻塞的调用, 但是不可能立即释放这 个套接字的资源, 必须等到连接完成或者超时后资源才会被释放 其函数原型如下 : void CancelBlockingCall(); 过滤和响应 Windows 特定的消息 OnMessagePending() 该函数是一个重载函数, 用来过滤和响应 Windows 特定的消息, 是一个高级的可重载 函数 如果 Windows 消息成功处理了则返回非 0 值, 否则返回 0 值 其函数原型如下 : virtual BOOL OnMessagePending() ; 第 2 章扫描可控计算机 41
28 42 Visual C++ 网络编程技术 WinInet 编程技术一个 Internet 客户端程序的目的是通过 Internet 协议如 HTTP FTP 等来存取网络数据源 ( 服务器 ) 的信息 客户端程序可以访问服务器获得如天气预报 股票价格 重要新闻数据, 甚至是与服务器交换信息 Internet 客户端程序可以通过外部网络 (Internet) 或内部网络 ( 一般为 Intranet) 访问服务器 为了开发 Internet 客户端程序 MFC 类库提供了专门的 Win32 Internet 扩展接口, 也就是 WinInet MFC 将 WinInet 封装在一个标准的 易于使用的类集合中 在编写 WinInet 客户端程序时, 你既可以直接调用 Win32 函数, 也可以使用 WinInet 类库 Win32 Internet 扩展提供了对普通 Internet 协议的访问, 这些协议包括 HTTP FTP 和 Gopher Gopher 已经渐渐淡出 借助于 WinInet 编程接口, 开发人员不必去了解 Winsock TCP/IP 和特定 Internet 协议的细节就可以编写出高水平的 Internet 客户端程序 WinInet 为几种协议 (HTTP FTP 和 Gopher) 提供了统一的函数集, 也就是 Win32 API 接口 利用这些统一的函数集, 大大简化了针对 HTTP FTP 等协议的编程, 从而轻松地将 Internet 集成到自己的应用程序中 在 Visual C++ 工程中提供有两种方式来使用 WinInet: 一种是直接调用 Win32 Internet 函数 ; 另一种是使用 WinInet 类库 MFC 对 WinInet 的封装是通过提供三个由 CStdioFile 派生类实现的 这三个派生类是 : CInternetFile CHttpFile 和 CGopherFile 对开发人员来说, 不管你以前是否用过 CStdioFile,WinInet 都是很好理解并且易于使用的 它使得存取 Internet 数据易如反掌, 使得 Internet 数据和本地数据的处理一致透明, 数据的存储位置已经不再重要 MFC WinInet 类有如下优点 : 缓冲器输入输出 数据的类型安全处理 许多函数的参数都是缺省值 对普通的 Internet 错误进行异常处理 自动清除打开的句柄和连接 WinInet 类包括 CInternetSession 等 10 多个类, 类名及功能如表 2-3 所示 表 2-3 WinInet 类名及功能介绍 类名 CInternetSession ( 父类 CObject) CInternetConnection ( 父类 CObject) CFtpConnection CGopherConnection CHttpConnection CInternetFile( 父类 CStdioFile) 功能 创建并初始化一个或几个同步 Internet 会话 管理一个到 Internet 服务器的连接 管理一个到 Internet 服务器的 FTP 连接及对外用户直接操作服务器上的文件和目录 管理一个到 Gopher 服务器的连接 管理一个到 HTTP 服务器的连接 使用 Internet 协议对远程系统的文件进行操作
29 续表 类名 功能 CGopherFile CHttpFile CFileFind( 父类 CObject) CFtpFileFind CGopherFileFind CGopherLocator( 父类 CObject) CInternetException( 父类 CException) 在 Gopher 服务器上进行读取和查找文件等操作在 HTTP 服务器上进行读取和请求文件等操作负责进行文件的查找在 FTP 服务器上查找文件在 Gopher 服务器查找文件从 Gopher 服务器上得到定位器用于处理网络异常 WinInet 有 3 个全局函数 : AfxParseURL: 该函数用来解析一个 URL 字符串, 并且返回服务类型 如果一个 URL 解析成功则返回非 0 值, 如果为空 URL 或者不包含已知的服务类型则返回 0 值 AfxGetInternetHandleType: 该函数用来判断一个网络服务类型, 这些返回网络服务类型在 AFXINET.H 中已定义, 如果 Handle 为空或者服务类型无法识别, 则返回 AFX_INET_SERVICE_UNK AfxThrowInternetException: 该函数用于处理网络异常 这些类和全程函数除 CFileFind 在 AFX.H 里声明之外, 其余都在 AFXINET.H 文件里声明 它们对 HTTP FTP 和 Gopher 等协议进行了高度抽象, 形成了一套高级 API 函数 利用这些 API 可以快速直接地开发 Internet 应用 例如, 连接到 FTP 服务器一般需要几个步骤, 而且需要做一些底层处理 但使用上述的 MFC 类提供的 API, 只需要对 CInternetSession::GetFTPConnection 进行一次调用, 便可以轻松建立连接 本章涉及的 MFC 常用类和控件 1.CString 类 MFC 库的 CString 类是 C++ 语言的一个很重要的扩展,CString 类有许多非常有用的操作和成员函数, 但最重要的一个特点莫过于它的动态内存分配, 完全不用担心 CString 对象的大小 CString 类的常用成员函数 : 1 int GetLength() const; 说明 : 获取 CString 类对象包含字符串的长度 ( 字符数 ) 2 BOOL IsEmpty() const; 说明 : 测试 CString 类对象包含的字符串是否为空 3 void Empty(); 说明 : 使 CString 类对象包含的字符串为空字符串 4 TCHAR GetAt( int nindex)const; 说明 : 获得字符串指定位置处的字符 第 2 章扫描可控计算机 43
30 44 Visual C++ 网络编程技术 5 void SetAt(int nindex, TCHAR ch); 说明 : 设定字符串指定位置处的字符 6 CString Left(int ncount)const; 说明 : 获取字符串左边 ncount 长度的字符串 7 CString Right(int ncount)const; throw(cmemoryexception); 说明 : 获取字符串右边 ncount 长度的字符串 8 MakeUpper 说明 : 将字符串中所有的字符全部转化成大写形式 9 MakeLower 说明 : 将字符串中所有的字符全部转化成小写形式 10 MakeReverse 说明 : 将字符串倒置, 即将字符的顺序颠倒, 第一个字符变成最后一个字符 11 int Replace(TCHAR chold, TCHAR chnew); int Replace(LPCTSTR lpszold, LPCTSTR lpsznew); 说明 : 将字符串中的字符子串 lpszold 替换成新的字符串 lpsznew 12 Find 原型 : int Find(TCHAR ch)const; int Find(LPCTSTR lpszsub)const; int Find(TCHAR ch, int nstart)const; int Find(LPCTSTR pstr, int nstart)const; 说明 : 在字符串中查找指定的字符或字符串 参数 ch 为要查找的字符 ;lpszsub 为要查 找的字符子串 ;nstart 指定查找的起始位置, 如缺省为从最左边开始 ;pstr 指向欲查找子串 的指针 13 ReverseFind 原型 :int ReverseFind(TCHAR ch)const; 说明 : 返回字符串中最后一个和指定的字符匹配的字符的下标 14 Compare 原形 :int Compare(LPCTSTR lpsz)const; 说明 : 比较两个字符串, 如果两个字符串相等, 返回值等于 0; 如果本对象大于参数字 符串, 返回值大于 0; 如果本对象小于参数字符串, 返回值小于 0, 比较时区分大小写 15 operator = 说明 : 将一个新的值赋予 CString 对象 16 operator + 说明 : 将两个字符串合并成一个新的字符串 在两个参数中必须有一个是 CString 类型 的, 而另一个参数可以是字符 字符指针或 CString 类型对象 17 operator += 说明 : 在一个字符串的后面再添加一个字符串或一个字符
31 2. 常用控件 按钮 编辑框和列表框 (1) 按钮 (CButton 类 ) 按钮是为数不多的 可以说是每个应用程序都要用到的 Windows 控件之一 即使是在 一个简单对话框显示信息的应用程序中, 通常也要在用完对话框后关闭它时使用 OK 按钮 生成按钮过程很简单, 只要在 VC 界面上的 控件 浮动面板中鼠标选择按钮, 拖动到 界面上即可 鼠标右键单击按钮, 可以选择修改按钮的属性 鼠标左键双击按钮,VC 向导 会自动帮助按钮添加按钮单击事件处理函数 ( 也可以在 建立类向导 中添加事件处理 ) (2) 编辑框 (CEdit) 编辑框是用来接收用户输入最常用的一个控件 在 VC 界面上的 控件 浮动面板 中鼠标选择编辑框, 拖动到界面上即可添加编辑框 因为编辑框通常要接收用户输入数 据, 或者将程序生成的数据显示到界面上的编辑框中, 所以需要在程序和编辑框之间进 行数据交换, 这就需要给编辑框添加一个关联的成员变量 在菜单 查看 里选择 建 立类向导, 弹出 建立类向导 对话框, 在对话框中选择 Member Variables 选项, 然后单击右侧的添加按钮, 给指定的编辑框添加成员变量 用户输入此编辑框的数据将 存放在该成员变量中, 程序也可以赋值给该成员变量, 然后把它显示到界面上 此处用 到一个函数 UpdateData 函数 UpdateData 原型 : BOOL UpdateData(BOOL bsaveandvalidate=true); 参数 bsaveandvalidate: 值为 true, 函数功能是将界面上用户输入编辑框的数据保存到 变量中 ; 值为 false, 函数功能是将数据在界面上对应编辑框中显示出来 (3) 列表框 (CListBox) 列表框可以用来列出一系列的文本, 每条文本占一行 在 VC 界面上的 控件 浮动面 板中鼠标选择列表框, 拖动到界面上即可添加列表框对象 为了使用列表框的各种功能, 首 先需要给列表框添加一个关联的成员变量, 添加方法与编辑框相同, 需要注意的是, 列表框 添加的成员变量类型要选择 CListBox 类型 通过该成员变量, 即可调用列表框的成员函 数 最常用的成员函数就是向列表框中添加文本的函数 在列表框类 (CListBox) 中有两个 长的有点相似的 成员函数 : int InsertString (int nindex, LPCTSTR lpsczitem) int AddString (LPCTSTR lpsczitem) 这两个函数都可被用来向列表中添加项目条 不同之处在于,InsertString 函数有两个参 数, 第一个参数为索引号, 设定为 -1 时, 项目条被插入到列表的末尾 ; 第二个参数与 AddString 函数的唯一参数相同, 为代表项目条中内容的字符串 使用 InsertString, 第一个 参数设定为 -1 时, 列表中的项目条的排列顺序严格按照源代码中语句的顺序排列 ; 使用 AddString 时, 列表中的项目条的顺序则按照英文字典序由上而下排列 2.5 本章技能训练实例 实验题目 : 简单的考试报名系统实现 实验目的 : 掌握使用 Socket 进行通信的基本方法和简单控件编程 第 2 章扫描可控计算机 45
32 46 Visual C++ 网络编程技术 实验内容 : 开发一个服务器端程序, 能够接收客户端发来的信息 ; 开发一个客户端程序, 能够将信息发送给服务器端, 可采用 CSocket 编程, 也可以用 WinSock 编程 实验步骤 : 打开两个 Visual C++ 窗口, 分别建立两个应用程序 MyServer 和 MyClient, 它们的界面如图图 2-12 和图 2-13 所示 图 2-12 服务器端界面 图 2-13 客户端界面 (1) 服务器端应用程序开发 界面中有一个文本编辑框, 一个让用户指定监听端口号, 对文本编辑框添加关联的成员变量 m_myport 界面下面是一个列表框, 给列表框添加一个关联的成员变量 m_show, 变量的类型是 CListBox 列表框用来显示所有用户的报名信息 编程思路如下: 1) 定义两个 Socket, 一个负责监听, 一个负责与客户端建立连接 2) 创建监听 Socket, 并指明监听端口 注意 : 端口号来自界面的文本框的输入 3) 当接到客户请求时, 建立连接, 此处进入循环 4) 接受客户发送的消息, 从客户发送的消息里解析出用户的信息, 添加到界面上的列表框里 5) 发送消息给客户
33 6) 关闭 Socket (2) 客户端应用程序开发 界面上有 5 个文本编辑框, 第一个让用户输入服务器 IP 地址, 第二个让用户输入服务器的监听端口号, 第三个让用户输入姓名, 第四个让用户输入单位, 第五个让用户输入考试科目 你需要给每个编辑框添加一个关联的成员变量, 名字分别是 m_serverip m_myport m_name m_code m_item 编程思路如下: 1) 定义一个 CSocket 对象 2) 创建 CSocket 对象 3) 连接服务器, 指明服务器的 IP 地址和服务器的监听端口 注意 :IP 地址和端口号都来自界面用户的输入 4) 获取文本编辑框中输入的信息, 并发送消息给服务器 5) 接收服务器的消息, 并显示到文本编辑框中 6) 关闭 Socket 对象 习题二 一 填空题 1. 目前最通用的网络编程接口就是 2. 建立套接字后, 需要为服务器端定义的这个监听的套接字指定一个地址及监听端口 (Port), 这样客户端才知道要连接哪一个地址的哪个端口, 为此需要调用 函数 3. 对于服务器编程中最重要的一步等待并接受客户的连接, 函数就完成了这个功能 4. 完成面向连接的协议的连接功能的函数是 5.CSocket 类是 的派生类, 继承了它封装的 WinSock API 6. 套接字有同步阻塞方式和 两种使用方法 7.MFC 中有两个主要的网络编程类 :CAsyncSocket 类和 类 二 选择题 1. 在服务器端建立一个套接字, 并进入实际的监听步骤的过程是 ( ) A.socket()->listen()->accept() B.socket()->bind()->listen()->accept() C.socket()->create()->listen()->accept() D.socket()->listen()->connect()->accept() 2. 在客户端调用 WinSock 的过程是 ( ) A.socket()->connect()->send() B.socket()->bind()->accept() C.socket()->listen()->accept() D.socket()->bind()->connect () 第 2 章扫描可控计算机 47
34 48 Visual C++ 网络编程技术 3.CAsyncSocket 类和 CSocket 类定义在头文件 ( ) 中 A.socket.h B.afxsock.h C.sock.h D.winsock.h 三 简答题 1. 什么是面向连接的网络通信? 2. 什么叫主机字节顺序? 什么叫网络字节顺序? 3. 什么是 MFC? 4. 分析阻塞方式和非阻塞方式的优缺点
Chapter 5- 运输层 (5)-2017
计算机网络 运输层编程 (5) 陈旺虎 [email protected] Review TCP 协议格式 TCP 可靠传输 为什么需要三次握手? A 发送一次确认的原因 应对出现 已失效的连接请求报文段 的情况, 即防止已失效的连接请求报文段突然又传到了 B 例 1:A 发出连接请求, 但该请求丢失,A 重传连接请求, 到达 B, 则正常 ; 一. 认识 Socket 应用层程序 流套接字接口
Chap04
Socket 编程介绍 Socket Socket 网络编程 按照操作系统 Windows 的 socket 编程 *nix 的 socket 编程 按照编程语 言 使 用C++ Java 的 socket 编程 使 用脚本语 言的 socket 编程 Socket 的 一些历史 Sockets 本来是 UNIX 操作系统下流 行行的 一种 网络编程接 口 (API), 在 4.2 BSD 中被 首先引
Guava学习之Resources
Resources 提供提供操作 classpath 路径下所有资源的方法 除非另有说明, 否则类中所有方法的参数都不能为 null 虽然有些方法的参数是 URL 类型的, 但是这些方法实现通常不是以 HTTP 完成的 ; 同时这些资源也非 classpath 路径下的 下面两个函数都是根据资源的名称得到其绝对路径, 从函数里面可以看出,Resources 类中的 getresource 函数都是基于
Chapter #
第三章 TCP/IP 协议栈 本章目标 通过本章的学习, 您应该掌握以下内容 : 掌握 TCP/IP 分层模型 掌握 IP 协议原理 理解 OSI 和 TCP/IP 模型的区别和联系 TCP/IP 介绍 主机 主机 Internet TCP/IP 早期的协议族 全球范围 TCP/IP 协议栈 7 6 5 4 3 应用层表示层会话层传输层网络层 应用层 主机到主机层 Internet 层 2 1 数据链路层
WinSockÍøÂç±à³Ì
WinSock 网络编程 1. 概述 80's 初,ARPA( 美国国防部高级研究计划局 ) fi 加利福尼亚大学 Berkeley 分校提供资金,fi 开发在 UNIX 下实现 TCP/IP 协议 fi 为 TCP/IP 开发了一个 API Socket 接口 ( 套接口 ) 俗称 Bekeley 套接口模型 90's 初,Microsoft 等公司 fi 基于 Bekeley 套接口模型 fi
帝国CMS下在PHP文件中调用数据库类执行SQL语句实例
帝国 CMS 下在 PHP 文件中调用数据库类执行 SQL 语句实例 这篇文章主要介绍了帝国 CMS 下在 PHP 文件中调用数据库类执行 SQL 语句实例, 本文还详细介绍了帝国 CMS 数据库类中的一些常用方法, 需要的朋友可以参考下 例 1: 连接 MYSQL 数据库例子 (a.php)
计算机网络实验说明
计算机网络实验说明 龚旭东 电三楼 420 lzgxd@mailustceducn 2011 年 11 月 1 日 龚旭东 (TA) 计算机网络实验说明 2011 年 11 月 1 日 1 / 20 Outline 1 实验系统介绍 实验环境实验流程 2 实验内容编程实验交互实验观察实验 3 一些控制台命令 4 实验报告说明 龚旭东 (TA) 计算机网络实验说明 2011 年 11 月 1 日 2
Slide 1
网络编程入门篇 利用 socket 实现 TCP 服务器 目录 基础知识 具体示例 示例代码讲解 基础知识 基础知识 socket 编程一般采用客户端 - 服务器模式 ( 即由客户进程向服务器进程发出请求, 服务器进程执行请求的任务并将执行结果返回给客户进程的模式 ) 今天我们要讲的就是如何利用 socket 编程实现基于 TCP 协议通信的服务器 首先我们先向大家展示 socket 编程的流程,
FY.DOC
高 职 高 专 21 世 纪 规 划 教 材 C++ 程 序 设 计 邓 振 杰 主 编 贾 振 华 孟 庆 敏 副 主 编 人 民 邮 电 出 版 社 内 容 提 要 本 书 系 统 地 介 绍 C++ 语 言 的 基 本 概 念 基 本 语 法 和 编 程 方 法, 深 入 浅 出 地 讲 述 C++ 语 言 面 向 对 象 的 重 要 特 征 : 类 和 对 象 抽 象 封 装 继 承 等 主
BOOL EnumWindows(WNDENUMPROC lparam); lpenumfunc, LPARAM (Native Interface) PowerBuilder PowerBuilder PBNI 2
PowerBuilder 9 PowerBuilder Native Interface(PBNI) PowerBuilder 9 PowerBuilder C++ Java PowerBuilder 9 PBNI PowerBuilder Java C++ PowerBuilder NVO / PowerBuilder C/C++ PowerBuilder 9.0 PowerBuilder Native
(Methods) Client Server Microsoft Winsock Control VB 1 VB Microsoft Winsock Control 6.0 Microsoft Winsock Control 6.0 1(a). 2
(2005-01-26) (2005-01-26) (2005-02-27) PIC_SERVER (9) VB TCP/UDP Visual Basic Microsoft Winsock Control (MSWINSCK.OCX) UDP TCP Client Server Visual Basic UDP/TCP PIC_SERVER UDP/TCP 1. Microsoft Winsock
/ / (FC 3)...
Modbus/TCP 1.0 1999 3 29 Andy Swales Schneider [email protected] ... 2 1.... 3 2.... 3 2.1.. 3 2.2..4 2.3..4 2.4... 5 3.... 5 3.1 0... 5 3.2 1... 5 3.3 2... 6 3.4 / /... 7 4.... 7 5.... 8 5.1 0... 9
目录 1 IPv6 快速转发 IPv6 快速转发配置命令 display ipv6 fast-forwarding aging-time display ipv6 fast-forwarding cache ipv6 fas
目录 1 IPv6 快速转发 1-1 1.1 IPv6 快速转发配置命令 1-1 1.1.1 display ipv6 fast-forwarding aging-time 1-1 1.1.2 display ipv6 fast-forwarding cache 1-1 1.1.3 ipv6 fast-forwarding aging-time 1-3 1.1.4 ipv6 fast-forwarding
目录 1 IPv6 快速转发 IPv6 快速转发配置命令 display ipv6 fast-forwarding aging-time display ipv6 fast-forwarding cache ipv6 fas
目录 1 IPv6 快速转发 1-1 1.1 IPv6 快速转发配置命令 1-1 1.1.1 display ipv6 fast-forwarding aging-time 1-1 1.1.2 display ipv6 fast-forwarding cache 1-1 1.1.3 ipv6 fast-forwarding aging-time 1-3 1.1.4 ipv6 fast-forwarding
《C语言程序设计》第2版教材习题参考答案
教材 C 语言程序设计 ( 第 2 版 ) 清华大学出版社, 黄保和, 江弋编著 2011 年 10 月第二版 ISBN:978-7-302-26972-4 售价 :35 元 答案版本 本习题答案为 2012 年 2 月修订版本 一 选择题 1. 设已定义 int a, * p, 下列赋值表达式中正确的是 :C)p = &a A. *p = *a B. p = *a C.p = &a D. *p =
华清远见就业优势倍增项目手册
Linux 网络编程 曾宏安 1. Internet 与 TCP/IP 协议 1 2 3 4 Internet 历史 OSI 模型与 TCP/IP 协议体系结构 TCP/IP 协议 TCP 和 UDP 协议 Internet 的历史 } Internet- 冷战 的产物 } 1957 年 10 月和 11 月, 前苏联先后有两颗 Sputnik 卫星上天 } 1958 年美国总统艾森豪威尔向美国国会提出建立
无类继承.key
无类继承 JavaScript 面向对象的根基 周爱 民 / aimingoo [email protected] https://aimingoo.github.io https://github.com/aimingoo rand = new Person("Rand McKinnon",... https://docs.oracle.com/cd/e19957-01/816-6408-10/object.htm#1193255
《C语言程序设计》教材习题参考答案
教材名称 : C 语言程序设计 ( 第 1 版 ) 黄保和 江弋编著清华大学出版社 ISBN:978-7-302-13599-9, 红色封面 答案制作时间 :2011 年 2 月 -5 月 一 选择题 1. 设已定义 int a, * p, 下列赋值表达式中正确的是 :C)p=&a 2. 设已定义 int x,*p=&x;, 则下列表达式中错误的是 :B)&*x 3. 若已定义 int a=1,*b=&a;,
VoIP Make a Rtp Call VoIP Abstract... 2 VoIP RTP...3 Socket IP...9 Config Two Voice-hub
VoIP... 2... 2 Abstract... 2... 3... 3 RTP...3 Socket...4...6...7 IP...9 Config Two Voice-hub... 10 1 12 VoIP VoIP voice-hub voice-hub Abstract At the beginning of this paper, we introducted the essential
Microsoft Word - CIN-DLL.doc
6.3. 调 用 动 态 链 接 库 (DLL) 相 对 于 CIN 来 讲,NI 更 推 荐 用 户 使 用 DLL 来 共 享 基 于 文 本 编 程 语 言 开 发 的 代 码 除 了 共 享 或 重 复 利 用 代 码, 开 发 人 员 还 能 利 用 DLL 封 装 软 件 的 功 能 模 块, 以 便 这 些 模 块 能 被 不 同 开 发 工 具 利 用 在 LabVIEW 中 使 用
untitled
Lwip Swedish Institute of Computer Science February 20, 2001 Adam Dunkels [email protected] (QQ: 10205001) (QQ: 329147) (QQ:3232253) (QQ:3232253) QQ ARM TCPIP LCD10988210 LWIP TCP/IP LWIP LWIP lwip API lwip
概述
OPC Version 1.6 build 0910 KOSRDK Knight OPC Server Rapid Development Toolkits Knight Workgroup, eehoo Technology 2002-9 OPC 1...4 2 API...5 2.1...5 2.2...5 2.2.1 KOS_Init...5 2.2.2 KOS_InitB...5 2.2.3
MASQUERADE # iptables -t nat -A POSTROUTING -s / o eth0 -j # sysctl net.ipv4.ip_forward=1 # iptables -P FORWARD DROP #
iptables 默认安全规则脚本 一 #nat 路由器 ( 一 ) 允许路由 # iptables -A FORWARD -i eth0 -o eth1 -j ACCEPT ( 二 ) DNAT 与端口转发 1 启用 DNAT 转发 # iptables -t nat -A PREROUTING -p tcp -d 192.168.102.37 dprot 422 -j DNAT to-destination
OOP with Java 通知 Project 3: 3 月 29 日晚 9 点 4 月 1 日上课
OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 3: 3 月 29 日晚 9 点 4 月 1 日上课 复习 Java 包 创建包 : package 语句, 包结构与目录结构一致 使用包 : import restaurant/ - people/ - Cook.class - Waiter.class - tools/ - Fork.class
《计算概论》课程 第十九讲 C 程序设计语言应用
计算概论 A 程序设计部分 字符数组与字符串 李戈 北京大学信息科学技术学院软件研究所 [email protected] 字符数组的定义 #include int main() char a[10] = 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' ; for (int i = 0; i < 10; i++) cout
The Library SysLibSockets
The Library SysLibSockets.lib...2 SysSockAccept...3 SysSockBind...3 SysSockClose...4 SysSockConnect...4 SysSockCreate...5 SysSockGetHostByName...5 SysSockGetHostName...6 SysSockGetOption...6 SysSockGetLastError...7
Slide 1
网络编程入门篇 Select: 非阻塞 Socket 编程 目录 基础知识 具体示例 注意事项 示例代码讲解 基础知识 基础知识 在 RT-Thread 使用 socket 网络编程时, 由于 socket 的 recv 和 send 的实现是阻塞式的, 因此当一个任务调用 recv() 函数接收数据时, 如果 socket 上并没有接收到数据, 这个任务将阻塞在 recv() 函数里 这个时候,
网络程序设计(socketAPI)
前言通信模型重要函数 网络程序设计 (socketapi) 孙永科 西南林业大学 2010 年 9 月 6 日 1 / 40 上节回顾 前言通信模型重要函数上节回顾本章重点 阻塞和非阻塞 socket 通信模型大字节顺序小字节顺序网络字节顺序 2 / 40 本章重点 前言通信模型重要函数上节回顾本章重点 1 通信模型基本概念 Socket 通信 Socket 地址 Socket 函数 2 重要函数获取主机信息
提问袁小兵:
C++ 面 试 试 题 汇 总 柯 贤 富 管 理 软 件 需 求 分 析 篇 1. STL 类 模 板 标 准 库 中 容 器 和 算 法 这 部 分 一 般 称 为 标 准 模 板 库 2. 为 什 么 定 义 虚 的 析 构 函 数? 避 免 内 存 问 题, 当 你 可 能 通 过 基 类 指 针 删 除 派 生 类 对 象 时 必 须 保 证 基 类 析 构 函 数 为 虚 函 数 3.
PTR89 应用程序编程接口 V1.00
PTR89 便携式热敏打印机 应用程序编程接口 V1.00 如有任何更改, 恕不另行通知 目录 1.0. 简介... 3 1.1. 文档范围和限制... 3 1.2. 参考... 3 2.0. 数据结构... 4 2.1. PRT_PAGE_MODE_PARAM... 4 3.0. API 函数... 5 3.1. Printer_Open... 5 3.2. Printer_Close... 5
C 1
C homepage: xpzhangme 2018 5 30 C 1 C min(x, y) double C // min c # include # include double min ( double x, double y); int main ( int argc, char * argv []) { double x, y; if( argc!=
引言 ftp 工作原理 FTP 客户端思考练习 要点回顾 1 ip 地址结构 2 字节顺序转换函数 3 IP 格式转换函数 2 / 29
引言 ftp 工作原理 FTP 客户端思考练习 网络程序设计 (FTP) 孙永科 西南林业大学 2010 年 9 月 17 日 1 / 29 引言 ftp 工作原理 FTP 客户端思考练习 要点回顾 1 ip 地址结构 2 字节顺序转换函数 3 IP 格式转换函数 2 / 29 引言 ftp 工作原理 FTP 客户端思考练习 本节重点 1 ftp 工作原理数据分析 TCPdump 过程分析 wireshark
本实验需要用到两个特征值, 两个特征值的属性各不相同, 我们同样在 SimpleGATTProfile 中新建即可, 接下来就开始吧 新建特征值表 : 表 3.3 串口透传特征值属性 长度 属性 UUID 功能 (byte) SIMPLEPROFILE_CHA R6 15 可读可写 FFF6 服务器
串口透传 前言 : 有了上面的基础, 接下来就可以打造无线串口功能了 实现平台 :WeBee CC2540 模块及功能底板 图 3.117 网蜂 CC2540 模块及功能底板实验现象 : 两台 PC 通过串口连接 CC2540, 通过设置好串口调试助手, 就可以相互收发信息 也可在一台 PC 利用两个串口实现这个功能 实验讲解 : 整个实验用到两个模块, 一个作为服务器 一个作为客户端, 重点为下面两个方向
Microsoft PowerPoint - 4. 数组和字符串Arrays and Strings.ppt [兼容模式]
Arrays and Strings 存储同类型的多个元素 Store multi elements of the same type 数组 (array) 存储固定数目的同类型元素 如整型数组存储的是一组整数, 字符数组存储的是一组字符 数组的大小称为数组的尺度 (dimension). 定义格式 : type arrayname[dimension]; 如声明 4 个元素的整型数组 :intarr[4];
untitled
1....2...2...6 2....10 3. UDP...15 4. TCP...16...16...16 1 1. PC COM1 COM2 COM1 COM2 DTU 2 3 4 COM1 COM1 COM2 COM ID 13900000000 DTU COM1 5 COM2 DTU DTU DTU DTU DTU DTU DTU ID ID 3031 3032 2 ID 13900000001
F515_CS_Book.book
/USB , ( ) / L R 1 > > > 2, / 3 L 1 > > > 2 + - 3, 4 L 1 了解显示屏上显示的图标 Wap 信箱收到一条 Wap push 信息 ( ) GSM 手机已连接到 GSM 网络 指示条越多, 接收质量越好 2 ...........................4.............................. 4 Micro SD (
UDP 8.2 TCP/IP OSI OSI 3 OSI TCP/IP IP TCP/IP TCP/IP Transport Control Protocol TCP User Datagram Protocol UDP TCP TCP/IP IP TCP TCP/IP TC
8 TCP/IP TCP/IP TCP OSI 8.1 OSI 4 end to end A B FTP OSI Connection Management handshake Flow Control Error Detection IP Response to User s Request TCP/IP TCP 181 UDP 8.2 TCP/IP OSI OSI 3 OSI 3 8.1 TCP/IP
嵌入式Linux块设备驱动开发解析
The success's road 嵌 入 式 LINUX 网 络 驱 动 开 发 Copyright 2007-2008 Farsight. All rights reserved. 要 点 Linux 网 络 设 备 驱 动 程 序 概 述 计 算 机 网 络 概 述 skbuf 数 据 结 构 介 绍 Linux 网 络 设 备 驱 动 程 序 API 介 绍 Linux 网 络 设 备 驱
一 登录 crm Mobile 系统 : 输入 ShijiCare 用户名和密码, 登录系统, 如图所示 : 第 2 页共 32 页
第 1 页共 32 页 crm Mobile V1.0 for IOS 用户手册 一 登录 crm Mobile 系统 : 输入 ShijiCare 用户名和密码, 登录系统, 如图所示 : 第 2 页共 32 页 二 crm Mobile 界面介绍 : 第 3 页共 32 页 三 新建 (New) 功能使用说明 1 选择产品 第 4 页共 32 页 2 填写问题的简要描述和详细描述 第 5 页共
res/layout 目录下的 main.xml 源码 : <?xml version="1.0" encoding="utf 8"?> <TabHost android:layout_height="fill_parent" xml
拓展训练 1- 界面布局 1. 界面布局的重要性做应用程序, 界面是最基本的 Andorid 的界面, 需要写在 res/layout 的 xml 里面, 一般情况下一个 xml 对应一个界面 Android 界面布局有点像写 html( 连注释代码的方式都一样 ), 要先给 Android 定框架, 然后再在框架里面放控件,Android 提供了几种框架,AbsoluteLayout,LinearLayout,
untitled
1 Outline 數 料 數 數 列 亂數 練 數 數 數 來 數 數 來 數 料 利 料 來 數 A-Z a-z _ () 不 數 0-9 數 不 數 SCHOOL School school 數 讀 school_name schoolname 易 不 C# my name 7_eleven B&Q new C# (1) public protected private params override
C6_ppt.PDF
C01-202 1 2 - (Masquerade) (Replay) (Message Modification) (Denial of Service) - ( ) (Eavesdropping) (Traffic Analysis) 8 1 2 7 3 6 5 4 3 - TCP SYN (SYN flood) Smurf Ping of Death LAND Attack Teardrop
<4D6963726F736F667420506F776572506F696E74202D20A1B6CFEEC4BFD2BB20B3F5CAB6BCC6CBE3BBFACDF8C2E7A1B7C8CECEF1C8FD20CAECCFA4544350A1A24950D0ADD2E9BACD4950B5D8D6B72E707074>
项 目 一 : 初 识 计 算 机 网 络 任 务 三 熟 悉 TCP/IP 协 议 和 IP 地 址 一. 学 习 要 求 : 学 习 要 求 及 难 点 1. 了 解 IP 协 议 TCP 协 议 和 UDP 协 议 2. 熟 悉 IP 地 址 的 划 分 和 分 类 3. 了 解 IPV6 的 地 址 结 构 二. 难 点 : 1. IP 地 址 三. 学 时 : 1. 理 论 教 学 :6
目 录(目录名)
目录 目录...1-1 1.1 域名解析配置命令... 1-1 1.1.1 display dns domain... 1-1 1.1.2 display dns dynamic-host... 1-1 1.1.3 display dns server... 1-2 1.1.4 display ip host... 1-3 1.1.5 dns domain... 1-4 1.1.6 dns resolve...
Basics of Socket Programming Please check the referenced links for the further description and examples. 1 Procedures for Socket Implementation 1. Create the server application (e.g. a simple shellscript)
Microsoft PowerPoint - string_kruse [兼容模式]
Strings Strings in C not encapsulated Every C-string has type char *. Hence, a C-string references an address in memory, the first of a contiguous set of bytes that store the characters making up the string.
OOP with Java 通知 Project 2 提交时间 : 3 月 14 日晚 9 点 另一名助教 : 王桢 学习使用文本编辑器 学习使用 cmd: Power shell 阅读参考资料
OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 2 提交时间 : 3 月 14 日晚 9 点 另一名助教 : 王桢 Email: [email protected] 学习使用文本编辑器 学习使用 cmd: Power shell 阅读参考资料 OOP with Java Java 类型 引用 不可变类型 对象存储位置 作用域 OOP
Microsoft Word - CX1000-HMI_程序开发_PLC通讯
用 VB.Net 开发 CX1000 的 HMI 第二部分和 TwinCAT PLC 通讯 一 TwinCAT 动态库 TwinCAT.Ads.dll The TwinCAT.Ads.dll 是一个.NET 类库, 它提供和 ADS 设备通讯的类 如果 TwinCAT PLC 运行在 IPC 上, 则需要添加的类库是路径 \TwinCAT\ADS Api\.NET\v1.1.4322 下的 TwinCAT.Ads.dll
概述
OPC Version 1.8 build 0925 KOCRDK Knight OPC Client Rapid Development Toolkits Knight Workgroup, eehoo Technology 2002-9 OPC 1...4 2 API...5 2.1...5 2.2...5 2.2.1 KOC_Init...5 2.2.2 KOC_Uninit...5 2.3...5
新版 明解C++入門編
511!... 43, 85!=... 42 "... 118 " "... 337 " "... 8, 290 #... 71 #... 413 #define... 128, 236, 413 #endif... 412 #ifndef... 412 #if... 412 #include... 6, 337 #undef... 413 %... 23, 27 %=... 97 &... 243,
TD
*TD-000212-05* 20- 应用实例 4 本例显示的是使用两个亚低 音扬声器和多个顶箱的双声 道 立体声 设置 除了各声道都增加了一个顶 箱外 也可以增加更多的顶 箱 本例和例 3 的情况一 致 声道 2 或 右声道 声道 1 或 左声道 要接到更多的顶箱 将最后 一个顶箱的全幅线路输出接 头处的线缆接到下一个顶箱 的全幅线路输入接头 在不 降低信号质量的情况下 最
OOP with Java 通知 Project 4: 4 月 19 日晚 9 点
OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 4: 4 月 19 日晚 9 点 复习 类的复用 组合 (composition): has-a 关系 class MyType { public int i; public double d; public char c; public void set(double x) { d
Microsoft PowerPoint - 3. 函数Functionl.ppt [兼容模式]
函数 Function 如何重用代码 How to reuse code 3 4 = 3*3*3*3 3 4,6 5 : 拷贝 - 粘帖代码 (Copy-paste code) 3 4,6 5,12 10 : 拷贝 - 粘帖代码 (Copy-paste code) Bad! 使用函数 (with a function) 使用函数 (with a function) 使用函数 (with a function)
Socket Programming in the Banking Collection Service Counter System
Socket Programming in the Banking Collection Service Counter System Gang WANG Hubei Radio and TV University, Wuhan, China Email: [email protected] Abstract: This paper describes the use of TCP / IP programming
NOWOER.OM m/n m/=n m/n m%=n m%n m%=n m%n m/=n 4. enum string x1, x2, x3=10, x4, x5, x; 函数外部问 x 等于什么? 随机值 5. unsigned char *p1; unsigned long *p
NOWOER.OM /++ 程师能 评估. 单项选择题 1. 下 描述正确的是 int *p1 = new int[10]; int *p2 = new int[10](); p1 和 p2 申请的空间 的值都是随机值 p1 和 p2 申请的空间 的值都已经初始化 p1 申请的空间 的值是随机值,p2 申请的空间 的值已经初始化 p1 申请的空间 的值已经初始化,p2 申请的空间 的值是随机值 2.
水晶分析师
大数据时代的挑战 产品定位 体系架构 功能特点 大数据处理平台 行业大数据应用 IT 基础设施 数据源 Hadoop Yarn 终端 统一管理和监控中心(Deploy,Configure,monitor,Manage) Master Servers TRS CRYSTAL MPP Flat Files Applications&DBs ETL&DI Products 技术指标 1 TRS
CC213
: (Ken-Yi Lee), E-mail: [email protected] 49 [P.51] C/C++ [P.52] [P.53] [P.55] (int) [P.57] (float/double) [P.58] printf scanf [P.59] [P.61] ( / ) [P.62] (char) [P.65] : +-*/% [P.67] : = [P.68] : ,
Linux网 络 编 程
Linux 网络编程 本章主要介绍一下网络编程的基本知识 由于书中后面章节都有一些简单的源程序实例来对各 章的基本概念进行解释, 因此必须具备必要的网络编程知识 在平时工作中, 为了查找安全漏洞, 也需要编写一些短小精悍的程序来代替复杂的手工命令输 入 在操作系统一章中对 Linux 中的 C 语言编程和调试已经作了介绍 本章在前两章的基础上, 首 先对 Linux 中的网络编程作介绍,Linux
Linux網路傳輸設定
Linux 網路傳輸設定 南台科技大學電子系 指導老師 : 侯安桑 班級 : 電子碩研一甲 學號 :M9830205 姓名 : 張嘉巖 Android 網路傳輸設定已經完成後, 接下來要開始設定 linux 網路傳輸, 目標是要將 linux 當作 server 端來設計, 使用的程式語言為 C 語言, 此作法會比 android 來的簡單許多, 只要顧慮程式流程和邏輯觀念是否正確即可, 下面會介紹
FortiADC SLB Virtual Server L7 方式部署介绍 版本 1.0 时间支持的版本作者状态反馈 2015 年 10 月 FortiADC v4.3.x 刘康明已审核
FortiADC SLB Virtual Server L7 方式部署介绍 版本 1.0 时间支持的版本作者状态反馈 2015 年 10 月 FortiADC v4.3.x 刘康明已审核 [email protected] 目录 简介... 3 Virtual Server L7 代理部署方式介绍... 3 Virtual Server L7 携带源地址代理部署方式介绍... 5 Fortinet
Microsoft PowerPoint - Socket programming.ppt [相容模式]
Basic Concept of Socket Socket programming 位於傳輸層和應用層之間 socket 是一種可做雙向資料傳輸的通道 讓應用層可以傳送資料給 socket, 或是從 socket 接收資料 Jimmy 2011/3/29 Concept of Socket Relation between Socket and Application Socket 的概念和檔案代碼觀念相似,
Microsoft PowerPoint - 8. 运算符重载 Operator Overloading.pptx
运算符重载 Operator Overloading class Point { public: ; double x_, y_; Why Operator Overloading? Point (double x =0, double y = 0):x_(x),y_(y) { int main(){ Point a(1., 2), b(3,4); Point c = a + b; return 0;
《信息通信网》实验指导书
IPv6 网络基础编程 一 实验目的 学习网络套接口 (socket) 编程, 掌握 Linux 操作系统下使用 TCP 协议进行通信的 IPv6 网络应用程序基本实现框架, 加深对 IPv6 协议的理解 二 预备工作和实验要求 将纯 IPv4 网络应用程序移植到纯 IPv6 环境下并没有多大困难 ; 对于典型的 C/S 结构程序, 我们只需对客户端和服务器端源代码进行简单修改, 然后重新编译它们
X713_CS_Book.book
/ / /USB ) ; ; C D ; ; B B 1 >> 2 3 B 1 ( > > ) 了解显示屏上显示的图标 Wap 信箱收到一条 Wap push 信息 GSM GPS ( ) 手机已连接到 GSM 网络 指示条越多, 接收质量越好 GPS 2 ...........................4.............................. 4 Micro SD (
经华名家讲堂
5.1 5.1.1 5.1.2 5.2 5.2.1 5.2.2 5.2.3 5.2.4 5.2.5 5.3 5.3.1 5.3.2 5.3.3 / 5.3.4 / 5.3.5 / 5.4 Internet 5.4.1 Internet 5.4.2 Intranet 1. 2. 1 31 5 5.1 5.1.1 Internet 1 Host 20 60 IBM 2000 2 20 60 20 60
PowerPoint 演示文稿
按钮对象 (button) 当 JavaScript 读到 标记中的 type 属性值为 button 时, 自动建立一个按钮对象, 并将该对象放到表单对象的 elements 数组当中 按钮对象包括 : 普通按钮 (button) 提交按钮 (submit) 重置按钮 (reset) 1. 使用按钮对象的格式 document.forms[ 索引值 ].elements[ 索引值
Contact base Smart Card intercept tools ---
虚拟卡软仿真说明 Virtual Card and Simulator manual 使用说明 Virtual card 软件仿真是指在 pc 上使用 vc 等工具, 配合 工具, 能够快速进行功能调试一种工程搭建方法 使用者通过一些简单设置, 即可将同一套代码共享在两个工程下 ( 例如一个 vc 工程, 一个 keil 工程 ), 这样代码的逻辑完全一致, 绝大多数问题都可以在 vc 环境下进行调试,
<4D F736F F D E4345C6BDCCA84323B1E0B3CCD2AAB5E3D6AED2BB2E646F63>
基于 WINCE 平台 C# 编程要点之一 本文主要介绍在基于 Windows CE 平台的英创嵌入式主板下进行 C#(Microsoft Visual Stdio.Net 2005) 应用程序开发时会常常用到的一些功能函数以及开发方法, 这些方法适用于英创采用 WinCE 平台的所有型号嵌入式主板, 包括 EM9000 EM9260 EM9160 等 本文要点包括 : 文件的删除和复制 如何获取存取设备的空间大小
ebook
32 IP 32.1 I n t e r n e t S O C K _ R A W I P 3 1) I C M P I G M P P i n g I C M P I C M P I C M P 1 9. 7 N e t / 3 R T M _ R E D I R E C T I C M P ( 1 9. 6 ) I C M P I G M P I G M 2) I P U D P I P U
SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基
开放数据处理服务 ODPS SDK SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基础功能的主体接口, 搜索关键词 "odpssdk-core" 一些
chap07.key
#include void two(); void three(); int main() printf("i'm in main.\n"); two(); return 0; void two() printf("i'm in two.\n"); three(); void three() printf("i'm in three.\n"); void, int 标识符逗号分隔,
/3/15 1, linux. linux,,. : 1.NAT ; 2. (load balance, virtual server);; 3. ; 4. ; 5. 6.VPN; 7. ; 8. ; 9.. (,
Yawl(yawl@docshownet) wwwdocshownet 2000/3/15 1, linux linux,, 1NAT ; 2 (load balance,virtual server);; 3 ; 4 ; 5 6VPN; 7 ; 8 ; 9 (,, )IP, (VPN,, ) IP, (call_in_firewall(),call_fw_firewall(),call_out_firewall(),
, 7, Windows,,,, : ,,,, ;,, ( CIP) /,,. : ;, ( 21 ) ISBN : -. TP CIP ( 2005) 1
21 , 7, Windows,,,, : 010-62782989 13501256678 13801310933,,,, ;,, ( CIP) /,,. : ;, 2005. 11 ( 21 ) ISBN 7-81082 - 634-4... - : -. TP316-44 CIP ( 2005) 123583 : : : : 100084 : 010-62776969 : 100044 : 010-51686414
ACE
ACE Socket Allen Long [email protected] http://www.huihoo.com huihoo - Enterprise Open Source 内容安排 如何访问 OS 服务 TCP/IP Socket 编程接口 使用 ACE 的 UDP 类进行网络编程 单播 广播 多播 Socket Interface 3 Socket API 概述 (1/2) Sockets
标准名称
设计文件 名称 编号 版本 Qtouch 驱动文件设计说明 V2.2.0 版权专有违者必究 标准模板 :Q/ST41.34-2010 编制 校核 审核 工艺 标准化 批准 版本号更改人更改日期更改说明变更编号 I 1 目的和范围 1.1 目的 本文档详细介绍了 Qtouch 驱动文件设计的基本格式和接口, 使用这些接口函数可实现与设备的通 讯 QTouch 通讯配置的连接和实时数据库的交互 2 规范性引用文件
