socket概念和常用函数

来源:互联网 发布:floyd算法计算步骤 编辑:程序博客网 时间:2024/04/30 11:25

socket编程
一、基础概念
定义:typedef unsigned int u_int; typedef u_int SOCKET;
用法:SOCKET相当于电话机,两台电话机建立连接后,双方就可以发送和接收数据了。
类型:1、流式套接字(stream socket),它提供双向的、有序的、无重复的以及无记录边界的数据流服务,适合处理大量数据。
         必须建立数据传输链路(连接),同时还必须对传输的数据进行验证,确保数据的准确性,系统开销大。
      2、数据报套接字(datagram socket),它也支持双向的数据流,但它是无连接的、不保证传输数据的准确性,但保留了
         记录边界。传输效率比较高。
      3、原始套接字(raw-protocol interface),它保存了数据包中的完整IP头,前面两种套接字只能收到用户数据,因此可
         以通过原始套接字对数据进行分析。
必须文件:以WinSock V2为例:Winsock2.h、Ws2_32.lib和W32_32.dll
套接字地址结构:
1、sockaddr结构——通用socket地址结构,和它等价的下面一个地址结构更常用。
struct sockaddr {
u_short sa_family; //sa_family为网络地址类型,该地址结构随选择的协议的不同而变化。
char sa_data[14]; /* up to 14 bytes of direct address */
};
2、sockaddr_in结构——用来标识TCP/IP协议下的地址,是专门针对Internet域的socket地址结构。
struct sockaddr_in {
short sin_family;        //网络地址类型,必须设定为AF_INET。
u_short sin_port;        //服务端口,注意不要使用已固定的服务端口。如果端口设置为0,则系统会自动分配一个唯一端口。
struct in_addr sin_addr; //为一个unsigned long的IP地址。
char sin_zero[8];        //sin_zero为填充字段,纯粹用来保证结构的大小
};
二、常用函数
1、对Winsock DLL进行初始化,协商Winsock的版本支持并分配必要的资源。(服务器端和客户端)
  int err;
 WSADATA wsaData;
 WORD wVersionRequested; 
 wVersionRequested = MAKEWORD( 2, 2 );
 err = WSAStartup( wVersionRequested, &wsaData );
 if ( err != 0 )
 {
  /* Tell the user that we could not find a usable */
  /* WinSock DLL.                                  */
  return false;
 } 
 /* Confirm that the WinSock DLL supports 2.2.*/
 /* Note that if the DLL supports versions greater    */
 /* than 2.2 in addition to 2.2, it will still return */
 /* 2.2 in wVersion since that is the version we      */
 /* requested.                                        */
 if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 )
 {
  /* Tell the user that we could not find a usable */
  /* WinSock DLL.                                  */
  WSACleanup();
  return false;
 }

2、创建套接字:(服务器端和客户端)
   SOCKET socket( int af, int type, int protocol );
   SOCKET sock=socket(AF_INET,SOCK_STREAM,IPPROTO_IP);

3、套接字的绑定:将本地地址绑定到所创建的套接字上。(服务器端)
   int bind( SOCKET s, const struct sockaddr FAR * name, int namelen )
  sockaddr_in addr;
  addr. sin_family=AF_INET;
  addr. sin_port= htons(80);
  addr. sin_addr.s_addr= inet_addr("127.0.0.1")
  int nResult=bind(s,(sockaddr*)&addr,sizeof(sockaddr));


4、套接字的监听:(服务器端)
   int listen(SOCKET s, int backlog )
   s为一个已绑定但未联接的套接字。
   backlog为指定正在等待联接的最大队列长度,这个参数非常重要,因为服务器一般可
   以提供多个连接。

5、套接字等待连接::(服务器端)
   SOCKET accept( SOCKET s, struct sockaddr FAR * addr, int FAR * addrlen )
   s为处于监听模式的套接字。
   sockaddr为接收成功后返回客户端的网络地址。
   addrlen为网络地址的长度。

6、套接字的连结:将两个套接字连结起来准备通信。(客户端)
   int connect(SOCKET s, const struct sockaddr FAR * name, int namelen )
   s为欲连结的已创建的套接字。
   name为欲连结的socket地址。
   namelen为socket地址的结构的长度。

7、套接字发送数据:(服务器端和客户端)
   int send(SOCKET s, const char FAR * buf, int len, int flags)
  flags为数据发送标记。
  返回值为发送数据的字符数。
    发送标记说明:
    flag取值必须为0或者如下定义的组合:0表示没有特殊行为。
    MSG_OOB表示数据应该带外发送,所谓带外数据就是TCP紧急数据。
    MSG_PEEK表示使有用的数据复制到缓冲区内,但并不从系统缓冲区内删除。
    MSG_DONTROUTE表示不要将包路由出去。

8、 套接字的数据接收:(客户端)
    int recv( SOCKET s, char FAR * buf, int len, int flags )
  s为准备接收数据的套接字
  
9、中断套接字连接:通知服务器端或客户端停止接收和发送数据。(服务器端和客户端)
  int shutdown(SOCKET s, int how)
  s为欲中断连接的套接字。
  How为描述禁止哪些操作,取值为:SD_RECEIVE、SD_SEND、SD_BOTH。
  #define SD_RECEIVE 0x00
  #define SD_SEND 0x01
  #define SD_BOTH 0x02

10、 关闭套接字:释放所占有的资源。(服务器端和客户端)
    closesocket( SOCKET s )

11、清理资源
   WSACleanup();
  
12、获得错误代码函数
   int  WSAGetLastError(void )

13、将主机的unsigned long值转换为网络字节顺序(32位),u_long  htonl(u_long hostlong);

14、将unsigned long数从网络字节顺序转换位主机字节顺序,u_long  ntohl(u_long netlong);

15、将主机的unsigned short值转换为网络字节顺序(16位):u_short  htons(u_short hostshort);

16、将unsigned short数从网络字节顺序转换位主机字节顺序u_short  ntohs(u_short netshort);

17、将用点分割的IP地址转换位一个in_addr结构的地址,实际上就是一个unsigned long值。
    计算机内部处理IP地址可是不认识如192.1.8.84之类的数据。
    unsigned long  inet_addr( const char FAR * cp );
    如:inet_addr("127.0.0.1")= 16777343

18、将网络地址转换位用点分割的IP地址
      char FAR *  inet_ntoa( struct in_addr in );
      举例:char * ipaddr=NULL;
      char addr[20];
      in_addr inaddr;
      inaddr. s_addr=16777343;
      ipaddr= inet_ntoa(inaddr);
      strcpy(addr,ipaddr);
  这样addr的值就变为127.0.0.1。注意意不要修改返回值或者进行释放动作。如果函数失败就会返回NULL值。
  
19、获取套接字的本地地址结构:
    int  getsockname(SOCKET s, struct sockaddr FAR * name, int FAR * namelen );
   
9、获取与套接字相连的端地址结构:
   int  getpeername(SOCKET s, struct sockaddr FAR * name, int FAR * namelen );

10、获取计算机名:
    int  gethostname( char FAR * name, int namelen );

11、根据计算机名获取主机地址:
    struct hostent FAR *  gethostbyname( const char FAR * name );
      hostent * host;
      char* ip;
      host= gethostbyname("xiaojin");
      if(host->h_addr_list[0])
      {
       struct in_addr addr;
       memmove(&addr, host->h_addr_list[0],4);
       //获得标准IP地址
       ip=inet_ ntoa (addr);
      }
      返回值为:hostent->h_name="computername"
      hostent->h_addrtype=2    //AF_INET
      hostent->length=4
      ip="127.0.0.1"
 

 

 

原创粉丝点击