当前位置:   article > 正文

网络编程 C++ ———WinSock_c++ winsock

c++ winsock
网络编程 C++ ———WinSock


                Windows Socket (即Winsock)以U.C. Berkeley大学BSD UNIX中流行的Socket接口为范例定义了一套microsoft Windows下网络编程接口。它不仅包含了人们所熟悉的Berkeley Socket风格的库函数;也包含了一组针对Windows的扩展库函数,以使程序员能充分地利用Windows消息驱动机制进行编程。
            通信的基础是套接口(Socket),一个套接口是通讯的一端。包含5种信息:
  •  本地协议端口
  •  本地主机地址
  •  远程协议端口
  •  远程主机地址
  •  协议 (程序在网络上传输数据是使用的协议)
        套接字分类:
  •    流式套接字 (SOCK_STREAM)         
             提供了双向、有序的、无重复的以及无记录边界的数据流服务,适合处理大量数据。它是面向联结的,必须建立数据传输链路,同时还必须对传输的数据进行验证,     确保数据的准确性。因此,系统开销较大。
  •    数据报套接字 (SOCK_DGRAM)         
          数据报套接字也支持双向的数据流,但不保证传输数据的准确性,但保留了记录边界。由于数据报套接字是无联接的,例如广播时的联接,所以并不保证接收端是否正在侦听。数据报套接字传输效率比较高。
  •    原始套接字   (SOCK_RAW)                
         原始套接字保存了数据包中的完整IP头,前面两种套接字只能收到用户数据。因此可以通过原始套接字对数据进行分析。支持更底层的协议 ,多用于实验新的协议和抓包嗅探。
  
         套接字结构体:  
  1. struct sockaddr {
  2. u_short sa_family; /* address family */
  3. char sa_data[14]; /* up to 14 bytes of direct address */
  4. };
      该结构体地址为通用Socket地址结构 。sa_family 可以选择不同的通信域。 下面的sockaddr_in则是专门针对Internet域的Socket地址结构体。
  1. struct in_addr {
  2. union {
  3. struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
  4. struct { u_short s_w1,s_w2; } S_un_w;
  5. u_long S_addr;
  6. } S_un;
    
          主机地址结构体:
  1. struct hostent {
  2. char FAR * h_name; /* official name of host */
  3. char FAR * FAR * h_aliases; /* alias list */
  4. short h_addrtype; /* host address type */
  5. short h_length; /* length of address */
  6. char FAR * FAR * h_addr_list; /* list of addresses */
  7. #define h_addr h_addr_list[0] /* address, for backward compat */
  8. };
h_name为主机名字。
h_aliases为主机别名列表。
h_addrtype为地址类型。
h_length为地址类型。
h_addr_list为IP地址,如果该主机有多个网卡,就包括地址的列表。

数据类型的基本定义:
typedef unsigned char u_char;
typedef unsigned short u_short;
typedef unsigned int u_int;
typedef unsigned long u_long;

几个常用的字节(网络 与主机)转换函数: 
unsigned long inet_addr(const char FAR * cp )
用法: unsigned long addr=inet_addr("192.1.8.84")
u_short ntohs(u_short nPort )     network to host short 
u_short htons(u_short nPort )
u_long htonl(u_long  nAddr)
u_long ntohl(u_long  nAddr)

WinSock 编程需要包含头文件Winsock2.0 和库文件WS2_32.LIB 和动态库WS2_32.DLL。在使用其库函数之前必须加载套接字库。
int WSAStartup ( WORD wVersionRequested, LPWSADATA lpWSAData );wVersionRequested
   wVersionRequested:一个WORD(双字节)型数值,指定了应用程序需要使用的Winsock规范的最高版本。
  lpWSAData 指向WSADATA数据结构的指针,用来接收Windows Sockets实现的细节。
在应用程序关闭套接字之后,应该调用WSACleanUp()终止Winsock DLL的调用,释放资源,以备下一次使用。


Winsock API

SOCKET socket(int af,int  type,int protocol)
int bind( SOCKET s, const struct sockaddr FAR * name, int namelen )
int listen(SOCKET s, int backlog )
SOCKET accept( SOCKET s, struct sockaddr FAR * addr, int FAR * addrlen )
int connect(SOCKET s, const struct sockaddr FAR * name, int namelen )
int send(SOCKET s, const char FAR * buf, int len, int flags )
int recv( SOCKET s, char FAR * buf, int len, int flags )
int shutdown(SOCKET s, int how)
int closesocket( SOCKET s )


int getsockopt(SOCKET s, int level, int optname, char FAR * optval, int FAR * optlen)
读取socket属性,s为欲读取属性的套接字。level为套接字选项的级别,大多数是特定协议和套接字专有的。如IP协议应为 IPPROTO_IP。
optname为读取选项的名称
optval为存放选项值的缓冲区指针。
optlen为缓冲区的长度
用法:
int ttl=0; //读取TTL值
int rc = getsockopt( s, IPPROTO_IP, IP_TTL, (char *)&ttl, sizeof(ttl));

int setsockopt(SOCKET s,int level, int optname,const char FAR * optval, int optlen)
设置socket属性,s为欲设置属性的套接字。
level为套接字选项的级别,用法同上。
optname为设置选项的名称
optval为存放选项值的缓冲区指针。
optlen为缓冲区的长度
用法:
int ttl=32; //设置TTL值
int rc = setsockopt( s, IPPROTO_IP, IP_TTL, (char *)&ttl, sizeof(ttl));

流式套接字编程模型:


数据报套接字编程模型:
        

WinSock的TCP通信 例子程序(VC++6.0 实现):
  1. //TCPSrv
  2. #include <stdio.h>
  3. #include <winsock2.h>
  4. #pragma comment (lib,"WS2_32.lib")
  5. int InitSock(BYTE minorVer=2,BYTE majorVer=2)
  6. {
  7. WSADATA wsadata;
  8. WORD sockVersion=MAKEWORD(minorVer,majorVer);
  9. if(::WSAStartup(sockVersion,&wsadata)!=0)
  10. {
  11. printf("failed WSAStarUp() ");
  12. return 0;
  13. }
  14. return 1;
  15. }
  16. void UnInitSock()
  17. {
  18. ::WSACleanup();
  19. }
  20. int main()
  21. {
  22. if(!InitSock())
  23. return 0;
  24. SOCKET sListen=::socket (AF_INET,SOCK_STREAM,IPPROTO_IP);
  25. if(sListen==INVALID_SOCKET)
  26. {
  27. printf("failed socket()");
  28. return 0;
  29. }
  30. // 填充地址结构体
  31. sockaddr_in sAddr;
  32. sAddr.sin_family=AF_INET;
  33. sAddr.sin_port=htons(7565);
  34. sAddr.sin_addr.S_un.S_addr=INADDR_ANY;
  35. if(::bind (sListen,(LPSOCKADDR)&sAddr,sizeof(sAddr))==SOCKET_ERROR)
  36. {
  37. printf("failed bind()");
  38. return 0;
  39. }
  40. if(::listen (sListen,2)==SOCKET_ERROR)
  41. {
  42. printf("failed listen()");
  43. return 0;
  44. }
  45. sockaddr_in cAddr;
  46. int nAddrLen=sizeof(cAddr);
  47. SOCKET sClient;
  48. char szText[]="TCP Server Demo! \r\n";
  49. while(TRUE)
  50. {
  51. sClient=::accept(sListen,(SOCKADDR*)&cAddr,&nAddrLen);
  52. if(sClient==INVALID_SOCKET)
  53. {
  54. printf("failed accpet()");
  55. continue;
  56. }
  57. printf("½ÓÊÕµ½Ò»¸öÁ¬½Ó£º%s \r\n",inet_ntoa(cAddr.sin_addr));
  58. ::send(sClient,szText,strlen(szText),0);
  59. ::closesocket(sClient);
  60. }
  61. ::closesocket(sListen);
  62. UnInitSock();
  63. return 0;
  64. }


  1. //TCPClient
  2. #include <stdio.h>
  3. #include <winsock2.h>
  4. #pragma comment (lib,"WS2_32.lib")
  5. int InitSock(BYTE minorVer=2,BYTE majorVer=2)
  6. {
  7. WSADATA wsadata;
  8. WORD sockVersion=MAKEWORD(minorVer,majorVer);
  9. if(::WSAStartup(sockVersion,&wsadata)!=0)
  10. {
  11. printf("failed WSAStarUp() ");
  12. return 0;
  13. }
  14. return 1;
  15. }
  16. void UnInitSock()
  17. {
  18. ::WSACleanup();
  19. }
  20. int main()
  21. {
  22. if(!InitSock())
  23. return 0;
  24. SOCKET s=::socket (AF_INET,SOCK_STREAM,IPPROTO_TCP);
  25. if(s==INVALID_SOCKET)
  26. {
  27. printf("failed socket()");
  28. return 0;
  29. }
  30. sockaddr_in servAddr;
  31. servAddr.sin_family=AF_INET;
  32. servAddr.sin_port=htons(7565);
  33. servAddr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1"); //ÔÚ±¾»ú²âÊÔ £¬ÔÚÁ½Ì¨²»Í¬»úÆ÷ÔÚʹÓÃÏìÓ¦µÄIpµØÖ·¼´¿É
  34. if(::connect(s,(sockaddr*)&servAddr,sizeof(servAddr))==-1)
  35. {
  36. printf("failed connect()");
  37. return 0;
  38. }
  39. char buff[256];
  40. int nRecv=::recv(s,buff,256,0);
  41. if(nRecv>0)
  42. {
  43. buff[nRecv]='\0';
  44. printf("接收到数据%s",buff);
  45. }
  46. ::closesocket(s);
  47. UnInitSock();
  48. return 0;
  49. }




                           


 



 



本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号