套接字主要有二种类型:
流式套接字(SOCK_STREAM);
数据报套接字(SOCK_DGRAM);
SOCK_STREAM:用于TCP协议通信
SOCK_DGRAM:用于UDP协议通信
套接字主要二类:
CAsyncSocket类与CSocket类
CasyncSocket类封装了异步套接字的基本功能,使用该类进行网络数据传输的步骤如下:
(1)、调用构造函数创建套接字对象
(2)、如果创建服务器套接字,则调用函数Bind()绑定本地IP和端口,然后调用函数Listen()监听客户端的请求。如果请求到来,则调用函数Accept()响应该请求。
如果创建客户端套接字,则直接调用函数Connect()连接服务器即可。
(3)、调用Send()等功能函数进行数据传输与处理。
(4)、关闭或销毁套接字对象。
CSocket类派生于CAsyncSocket类,具有串行化功能,通过将CSock'ect类与CSocketFile类和CArchive类一起使用,能够很好的管理数据和发送数据,使用该类进行网络数据传输的步骤如下:
(1)、创建CSocket类对象
(2)、如果创建服务器端套接字,则调用函数Bind()绑定本地ip和端口,然后调用函数Listen()监听客户端的请求。如果请求到来,则调用函数Accept()响应该请求。
如果创建客户端套接字,则直接调用函数Connect()连接服务器即可。
(3)、创建与CSocket类对象相关联的CSocketFile类对象
(4)、创建与CSocketFile类相关联的CArchive对象
(5)、使用CArchive类对象在客户端与服务器之间进行数据传输
(6)、关闭或销毁CSocket类、CSocketFile类和CArchive类的3个对象
————————————————————————————————————————————————————————————————————————————
在Socket套接字编程下,因为套接字需要在各种网络协议中使用,为了区分程序所使用的网络协议必须使用统一的寻址方式。
在Winsock(Socket API)中,用户可以使用TCP/IP地址家族中统一的套接字地址结构解决TCP/IP寻址中可能出现的问题。
套接字地址结构定义如下:
struct sockaddr_in{ short sin_family; //指定地址家族即地址格式 unsigned short sin_port; //端口号码 struct in_addr sin_addr; //IP地址 char sin_zero[8]; //留作备用,需要指定为0 };
在这个结构的最后一个成员并未实际使用,主要是为了与第一个版本的套接字地址结构大小相同而设置。在实际使用时,将这8字节直接设为0即可。
结构成员变量sin_addr表示32位的IP地址结构。结构定义如下:
struct in_addr { union { struct { unsigned char s_b1, s_b2, s_b3, s_b4; }S_un_b; //用4个u_char字符描述IP地址 struct { unsigned short s_w1, s_w2; //用2个u_short类型描述IP地址 }S_un_w; unsigned long S_addr; //用1个u_long类型描述IP地址 }S_un; };
sockaddr_in addr; addr.sin_addr.S_un.S_addr = inet_addr("218.6.132.5");
——---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
在socket套接字编程中,传输数据的排列顺序以网络字节顺序和主机字节顺序为主。
通常情况下,如果用户将数据通过网络发送时,需要将数据转换成网络字节顺序排列。
如果用户是将网络中接收的数据存储在本地计算机上,那么需要将数据转换成主机字节顺序排列。
函数定义如下:
u_short htons(u_short hostshort); u_long htonl(u_long hostlong); u_long ntohl(u_long netlong); u_short ntohs(u_short netshort); unsigned long inet_addr(const char FAR * cp); //将一个字符串IP转换到以网络字节顺序排列的IP地址 char FAR * inet_ntoa(struct in_addr in); //将一个以网络字节顺序排列的IP地址转换为一个字符串IP
sockaddr_in addr; in_addr in_add; addr.sin_family = AF_INET; addr.sin_port = htons(80); addr.sin_addr.S_un.S_addr = inet_addr('127.0.0.1'); //将字符串IP转换为网络字节顺序排列的IP char addres[] = inet_ntoa(addr.sin_addr.S_un.S_addr);//将网络字节顺序排列的IP转换为字符串IP
——————————————————————————————————————————————————
1、创建套接字
2、绑定地址信息
BOOL Bind(const SOCKADDR* lpSockAddr, int nSockAddrLen)
lpSockAddr指定将要绑定的服务器地址结构, nSockAddrLen表示地址结构的长度
代码如下:
CSocket sock; sockaddr_in addr; in_addr in_add; addr.sin_family = AF_INET; addr.sin_port = htons(80); addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); sock.Bind((SOCKADDR*)addr, sizeof(addr));
参数nConnectionBacklog表示套接字监听客户端请求的最大数目,该参数的有效范围是1到5,默认为5,表示该套接字只能监听5个客户端所发送的连接请求。
3、连接服务器
BOOL Connect( const SOCKADDR* lpSockAddr, int nSockAddrLen);
参数lpSockAddr表示将连接的服务器地址结构,参数nSockAddrLen表示地址结构的长度大小
代码如下:
CSocket sock; sockaddr_in addr; in_addr in_add; addr.sin_family = AF_INET; addr.sin_port = htons(80); addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); sock.Connect((SOCKADDR*)addr, sizeof(addr));
virtual int Send(const void* lpBuf, int nBufLen, int nFlags = 0);
virtual int Receive(void* lpBuf, int nBufLen, int nFlags = 0);
函数Send()用于发送指定缓冲区的数据,函数Recvive()用于接收对方发送的数据,并将数据存放在指定缓冲区。
参数lpBuf表示数据缓冲区地址,参数nBufLen表示数据缓冲区的大小。参数nFlags表示数据发送或接收的标识。
CSocket sock; char buff[] = 'a'; sock.Send(&buff, sizeof(buff), 0); sock.Receive(&buff, sizeof(buff), 0);
sock.Close();