第2章 Winsock编程接口

更新时间:2023-05-10 21:21:01 阅读量: 实用文档 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

第二章 Winsock编程接口Windows为传输层的编程提供了socket函数, 即Winsock ;Winsock是windows下网络编 程的标准接口,是真正的协议无关的接口。用 户可以非常方便的使用winsock开发基于TCP 或UDP的应用程序。

几个重要的知识点回顾

点击打开

Windows Socket, Protocols and ApplicationsApplication

WinSock.dll

FTP WinSock.dll

Remote Access Service (RAS) TCP/IP IPX AppleTalk NetBIOS

FTP TCP/IP

Modem Phone Line

Network Drivers

LAN

TCP/IP协议核心与应用程序关系图

2.1 Winsock库两个版本 Winsock1、Winsock2,一般用后一版本。

头文件:winsock2.h--socket函数、相关结构的声明和定义 链接库: WS2_32.lib--引入库,DLL的导出接口描述 或者包含预处理命令 #pragma comment(lib,”WS2_32”)UDPserver

2.1.1 winsock库的装入和释放每个winsock应用程序必须加载相应版本的winsock DLL。如果在调用winsock 函数前没有加载,会返回SOCKET_ERROR,出错代码是WSANOTINITIALISED. int WSAStartup( WORD wVersionRequested, LPWSADATA lpWSAData //指向WSADATA结构的指针,用来返回DLL库的信息 ); WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 2, 2 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { /* Tell the user that we could not find a usable WinSock DLL. */ return; }

WSAStartup使用所加载库的版本信息填充lpWSAData。 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;

对于每一个WSAStartup的调用必须对应一个WSACleanup调用:

int WSACleanup (void); The Windows Sockets WSACleanup function terminates(终止) use of the Ws2_32.dll.

2.1.2 封装CinitSocket类#include <winsock2.h> #pragma comment(lib, "WS2_32") // 链接到WS2_32.lib class CInitSock { public: CInitSock(BYTE minorVer = 2, BYTE majorVer = 2) { // 初始化WS2_32.dll WSADATA wsaData; WORD sockVersion = MAKEWORD(minorVer, majorVer); if(::WSAStartup(sockVersion, &wsaData) != 0) { exit(0); } ! } ~CInitSock() 为了使用方便,因为每次写网络程序 { 都必须加载和释放winsock库 ::WSACleanup(); } };

2.2Winsock的寻址方式和字节顺序2.2.1 Windows寻址tcp/ip使用ip地址和端口号确定一个访问地址。通用插口地址结构 struct sockaddr { u_short sa_family; char sa_data[14]; };/* Socket address family */

/* Maximum size of all of the different socket address structures */

SOCKADDR_IN Structure在Winsock定义了sockaddr结构的TCP/IP版本sockaddr_in;在 winsock中,应用程序通过SOCKADDR_IN结构来指定IP地址和 端口号: struct sockaddr_in{ short sin_family; //Address family; must be AF_INET unsigned short sin_port; //Internet Protocol (IP) port struct in_addr sin_addr; //IP address in netwo

rk byte order. char sin_zero[8]; /*空字节,要设为0。Padding to make structure the };same size as SOCKADDR */

注意:(1) IP port中, 0~1023由Internet已分配数值权威机构 IANA分配和控制; 1024~65535 用户自己分配

(2) struct in_addr的定义如下:

struct in_addr{ union { 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; } S_un; };

两个转换函数

unsigned long inet_addr( const char *cp );converts a string containing an (Ipv4) Internet Protocol dotted address into a proper address for the IN_ADDR structure. Ex: 10.0.0.1 00001010 00000000 00000000 00000001

注意:该函数返回的32位串是网络字节顺序存储的。

char FAR * inet_ntoa( struct in_addr in );converts an (Ipv4) Internet network address into a string in Internet standard dotted format.

Ex: 00001010 00000000 00000000 00000001 10.0.0.1

2.2.2 字节顺序

我们知道,在操作系统中,IBM AIX,Sun OS, HP Unix,Solaris采用大数在前的字节顺序;而 Digital Unix,Linux,BSDi,SystemV4,DOS, Windows 9x/2000/NT则采用的是小数在前的字 节顺序,也称为主机字节顺序。 TCP/IP统一使用大数在前的字节顺序,也称为 网络字节顺序。

字节顺序转换函数:

u_short htons( u_short hostshort );converts a u_short from host to TCP/IP network byte order

u_short ntohs( u_short netshort );converts a u_short from TCP/IP network byte order to host byte order

2.2.3获取地址信息1、获取本机地址信息 2、获取MAC地址

2.3 Winsock编程详解

2.3 Winsock编程详解2.3.1 Winsock编程流程1、套接字对象的创建和关闭

★ SOCKET socket( int af, int type, int protocol );--af [in] Address family specification. AF_INET --type [in] Type specification for the new socket. SOCK_STREAM ; SOCK_DGRAM ; SOCK_RAW --protocol [in] 0

★ int closesocket( SOCKET s );

2、绑定套接字到指定的IP地址和端口

int bind( SOCKET s, //Descriptor identifying an unbound socket const struct sockaddr FAR *name,/*Address to assign to the socket from the SOCKADDR structure*/

int namelen

//Length of the value in the name parameter

);Function: Associates a local address with a socket

SOCKET sListen = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(sListen == INVALID_SOCKET) { printf("Failed socket() \n"); 0 return 0; }

// 填充sockaddr_in结构 sockaddr_in sin; inet_addr(“127.0.0.1”) sin.sin_family = AF_INET; sin.sin_port = htons(4567); sin.sin_addr.S_un.S_addr = INADDR_ANY;// 绑定这个套节字到一个本地地址 if(::bind(sListen, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR) { printf("Failed bind() \n"); struct sockaddr * return 0; }

3.设置套接字进入监听状态int listen( SOCKET s, int backlog );places a socket a state where it is listening for an incoming connection

s

Descriptor identifying a bound, u

nconnected socket. Maximum length of the queue of pending(未处理的) connections.

backlog

本文来源:https://www.bwwdw.com/article/gewe.html

Top