当前位置:文档之家› (整理)冒险者小游戏模式分析

(整理)冒险者小游戏模式分析

苏州科技学院电子与信息工程学院课程实验报告书课程名称:计算机网络实验班级:计算机0911 班学号:0920107124姓名:徐镇韬教师:陶滔二○一一年十二月实验四TCP/IP 网络编程实验一、实验目的1.掌握TCP/IP 协议的基本知识,TCP/IP 协议的基本工作原理。

2.理解Socket 的基本概念和工作原理,掌握Socket 建立、监听、连接、数据发送和接收的方法。

3.进一步掌握客户/服务器应用程序的设计方法,利用底层的W indows Sockets API函数实现简单的Winsock 网络应用程序设计,提高Windows 平台上的Socket 编程能力。

二、实验内容1.设计一程序,利用UDP 实现点对点聊天。

2.设计一程序,实现Web 服务器的基本功能。

三、相关知识Windows Sockets 规范以U.C. Berkeley 大学BSD UNIX 中流行的Socket 接口为范例定义了一套Micosoft Windows 下网络编程接口。

它不仅包含了人们所熟悉的Berkeley Socket 风格的库函数,也包含了一组针对Windows 的扩展库函数,以使程序员能充分地利用Windows 消息驱动机制进行编程。

目前的Windows Sockets 2 是一套开放的、支持多种协议的Windows 下的网络编程接口。

Winsock 已经基本上实现了与协议无关,使用Winsock 来调用多种协议的功能,但较常使用的是TCP/IP 协议。

根据网络通信的特性,套接字可分为两类:面向连接协议( TCP )的流套接字(SOCK_STREAM )和面向无连接协议( UDP )的数据报套接字( SOCK_DGRAM )。

对于要求精确传输数据的Windows Sockets 网络通信程序,一般采用流式套接字。

流式套接字提供了一个面向连接的、可靠的、数据无错的、无重复发送的及按发送顺序接收数据的服务。

其内设流量控制,避免数据流超限,同时,数据被看作是字节流,无长度限制。

套接字可以处于阻塞模式和非阻塞模式。

调用一个阻塞模式的函数,都会产生相同的后果——耗费或长或短的时间等待操作完成。

而当套接字处于非阻塞模式时,API 函数的调用会立即返回,大多数情况下这些调用会“ 失败”,并返回一个WSAWOULDBLOCK 错误,它表示请求的操作没有时间完成。

Winsock 的套接字I/O 模型可以帮助应用程序判断一个套接字何时可供读写。

1. Windows Sockets 主要函数Socket 实际在计算机中提供了一个通信接口,可以通过这个接口与任何一个具有Socket 接口的计算机通信。

应用程序在网络上传输、接收的信息都通过这个Socket 接口来实现。

在应用开发中就像使用文件句柄一样,可以对Socket 句柄进行读、写操作。

Windows Sockets API 包括很多函数,但其中最常用的主要函数如下所述:(1)启动Winsock 服务WSAStartup()格式:int WSAStartup( WORD wVersionRequested, LPWSADATA lpWSAData );功能:此函数是对Windows Sockets DLL 进行初始化,只有此函数调用成功后,才可以再调用其他Windows Sockets DLL 的函数。

参数:wVersionRequested 指明程序请求使用的Socket 版本,其中高位字节指明副版本、低位字节指明主版本;lpWSAData 返回请求的Socket 的版本信息。

返回值:成功返回0。

示例:假如一个程序要使用 2.2 版本的Socket ,可用如下程序代码:WORD wVersionRequested;WSADATA wsaData;int err;wVersionRequested = MAKEWORD( 2, 2 );err = WSAStartup( wVersionRequested, &wsaData );(2)终止Windows Sockets 服务WSACleanup()格式:int WSACleanup (void);功能:当应用程序不再需要使用Windows Sockets DLL 时,解除与Socket 库的绑定并且释放Socket 库所占用的系统资源。

(3)创建套接字socket()格式:SOCKET socket(int af,int type,int procotol); 功能:创建一个能够进行网络通信的套接字。

参数:af通指定应用程序使用的通信协议的协议族,对于TCP/IP协议族,该参数置PF_INET 。

type 要创建的套接字类型,流套接字类型为SOCK_STREAM 、数据报套接字类型为SOCK_DGRAM 。

procotol 指定应用程序所使用的通信协议。

返回值:成功返回新创建的套接字的描述符,失败返回INV ALID_SOCKET 。

示例:下面的代码是一个创建流套接字的示例:struct protoent *ppt;ppe=getprotobyname("tcp");SOCKET ListenSocket=socket(PF_INET,SOCK_STREAM,ppt->p_proto);(4)绑定本机地址bind()格式:int bind(SOCKET s,const struct sockaddr FAR * name,int namelen); 功能:将本机地址与所创建的套接字号联系起来。

参数:s 是由socket()调用返回的并且未作连接的套接字描述符(套接字号)。

name指定一个sockaddr 结构。

namelen 是name 的长度。

返回值:成功返回0,否则返回SOCKET_ERROR 。

地址结构说明:struct sockaddr_in} sa_family 指定地址族, 对于 TCP/IP 协议族的套接字, 给其置 AF_INET 。

当对 TCP/IP 协议族的套接字进行绑定时,通常使用另一个地址结构:struct sockaddr_in {short sin_family; u_short sin_port;struct in_addr sin_addr;char sin_zero[8];};其中 sin_family 置 AF_INET ,sin_port 指明端口号, in_addr 结构体中只有一个唯一 的字段 s_addr ,表示 IP 地址,该字段是一个整数,一般用函数 inet_addr() 把字符串形式的 IP 地址转换成 unsigned long 型的整数值后再赋给 s_addr 。

有的服务器是多宿主机, 至 少有两个网卡,那么运行在这样的服务器上的服务程序在为其 Socket 绑定 IP 地址时可 以把 htonl(INADDR_ANY) 赋给 s_addr ,这样做的好处是不论哪个网段上的客户程序都能 与该服务程序通信; 如果只给运行在多宿主机上的服务程序的 Socket 绑定一个固定的 IP 地址,那么就只有与该 IP 地址处于同一个网段上的客户程序才能与该服务程序通信。

示例:以下代码是是一个 bind 函数调用的例子:struct sockaddr_in saddr; saddr.sin_family = AF_INET; saddr.sin_port= htons(8888); saddr.sin_addr.s_addr = htonl(INADDR_ANY);bind(ListenSocket,(struct sockaddr *)&saddr,sizeof(saddr)) ;(5) 监听连接 listen()格式: int listen(SOCKET s, int backlog);功能:服务程序可以调用 listen 函数使其流套接字 s 处于监听状态。

参数:指定监听状态的流套接字 s ,它将维护一个客户连接请求队列,该队列最多容纳参数 backlog 个客户连接请求。

返回值:成功返回 0,失败返回 SOCKET_ERROR 。

(6) 建立套接字连接 connect() 和 accept()格式: int connect(SOCKET s,const struct sockaddr FAR * name,int namelen);SOCKET accept(SOCKET s,struct sockaddr FAR * name,int FAR *addrlen);{short sin_family;u_short sin_port;struct in_addrsin_addr; charsin_zero[8];//AF_INET //16 位端口号,网络字节顺序 //32 位 IP 地址,网络字节顺序功能:服务程序调用accept()函数从处于监听状态的流套接字s 的客户连接请求队列中取出排在最前的一个客户请求,并且创建一个新的套接字来与客户套接字创建连接通道。

客户程序调用connect() 函数来使客户Socket s 与监听于name 所指定的计算机的特定端口上的服务Socket 进行连接。

参数:同bind() 。

返回值:对于accept()连接成功返回新创建的套接字的描述符,以后与客户套接字交换数据的是新创建的套接字,如果失败返回INV ALID_SOCKET 。

对于connect() 连接成功返回0,如果失败返回SOCKET_ERROR 。

示例:以下代码是一个调用accept()的例子:struct sockaddr_in ServerSocketAddr;int addrlen; addrlen=sizeof(ServerSocketAddr);ServerSocket=accept(ListenSocket,(struct sockaddr *)&ServerSocketAddr, &addrlen);以下代码是调用connect() 的例子:struct sockaddr_in daddr; memset((void*)&daddr,0,sizeof(daddr)); daddr.sin_family=AF_INET;daddr.sin_port=htons(8888);daddr.sin_addr.s_addr=inet_addr("133.197.22.4");connect(ClientSocket,(struct sockaddr *)&daddr,sizeof(daddr));(7)流套接字数据发送与接收send()和recv() 格式:int send(SOCKET s,constchar FAR * buf,int len,int flags);int recv(SOCKET s,const char FAR * buf,int len,int flags);功能:流套接字( TCP )数据的发送与接收。

相关主题