使用基本的socket函数

Posted Autumn の Box

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用基本的socket函数相关的知识,希望对你有一定的参考价值。

1.socket库的2.2版本的文件:

  dll文件:ws2_32.dll

  lib文件:ws2_32.lib

  头文件:<WINSOCK2.H>

2.socket库的初始化和卸载

  2.1-初始化socket库

    int WSAStartup (

             WORD wVersionRequested, //请求使用的库的版本

                 LPWSADATA lpWSAData  //返回可用的库的信息

    );

  2.2-卸载socket库

    WSACleanup();

  2.3-MFC提供了一个AfxSocketInit函数,该函数内部自动调用了WSAStartup函数和WSACleanup函数,利用该函数加载和卸载socket库时,不需要为工程连接ws2_32.lib库文件,仅需包含头文件:#include <Afxsock.h>,且必须在应用的程序类的InitInstance函数中调用该函数,该函数加载的是1.1版本的socket库;

    BOOL AfxSocketInit( WSADATA* lpwsaData = NULL );

    返回值:函数调用成功返回非0值,调用失败返回0;

3.TCP通信

  3.1-TCP服务器

    1--创建服务器端socket

      SOCKET socket (int af, int type, int protocol);

        af:指定地址族,AF_UNIX/AF_LOCAL/AF_FILE--本地通信;AF_INET--网络通信IPv4(主用);AF_INET6--网络通信IPv6(前缀AF替换成PF效果一样);

        type:指定socket类型,SOCK_STREAM--流式套接字,SOCK_DGRAM--数据报式套接字;

        protocol:推荐为0;

      函数返回值:成功返回socket描述符;失败返回一个INVALID_SOCKET值,错误信息可通过WSAGetLastError函数返回;

    2--绑定IP地址和端口(bind)

      int bind (SOCKET s, const struct sockaddr FAR*  name, int namelen);

        s:要绑定的套接字;

        name:指定该套接字的通信地址信息,指向sockaddr结构体或sockaddr_un结构体或sockaddr_in结构体的指针变量;

        nameLen:指定地址结构的长度;

      函数返回值:成功返回0;失败返回一个SOCKET_ERROR,错误信息可通过WSAGetLastError函数返回;

      通信地址包括结构体:

        struct sockaddr  --主要用于做函数的参数,不负责存储数据;

          struct sockaddr {

              unsigned short   sa_family;  //指定地址族

              char             sa_data[14];  //要求一块内存分配区,起占位作用

          };

        struct sockaddr_in  --负责存储网络通信的地址数据

          struct sockaddr_in{

              short            sin_family;  //指定地址族

              unsigned short      sin_port;  //端口号

              struct   in_addr      sin_addr;  //主机IP地址

              char               sin_zero[8];

          };

          注:若本地机器具有多个网卡,则每个网卡均有自己的IP地址,可将IP地址指定为INADDR_ANY,允许向分配给本地机器的各个IP地址发送或接收数据;

    3--监听(listen)

      int listen ( SOCKET s, int backlog );

        s:套接字;

        backlog:SOMAXCONN,设置等待队列的最大长度(可接收的请求个数);

    4--等待客户端连接并接受(accept)

      SOCKET accept ( SOCKET s, struct sockaddr FAR* addr, int FAR* addrlen );

        s:套接字;

        addr:指向一个缓冲区,该缓冲区用来保存服务器端接受的发起连接的客户端的IP地址信息和端口信息;

        addrlen:返回包含地址信息的长度;

      函数返回值:成功返回socket描述符;失败返回一个INVALID_SOCKET值,错误信息可通过WSAGetLastError函数返回;

    5--数据收发(send/recv)

      int send ( SOCKET s, const char FAR * buf, int len, int flags );

        s:套接字;

        buf:指向一个缓冲区,该缓冲区包含将要传递的数据;

        len:缓冲区的长度;

        flags:设为0;

      int recv ( SOCKET s, char FAR* buf, int len, int flags );

        s:套接字;

        buf:指向一个缓冲区,用来保存接收的数据;

        len:缓冲区的长度;

        flags:设为0;

    6--关闭socket

      int closesocket ( SOCKET s );

 

    通过netstat -an,查看网络端口状态

  

  3.2-TCP客户端

    1--创建客户端socket

    2--连接服务器,如果是本机 inet_addr("127.0.0.1");

      int connect ( SOCKET s, const struct sockaddr FAR*  name, int namelen );

        s:套接字;

        name:设定连接的服务器端地址信息;

        namelen:指定服务器端地址的长度;

    3--数据收发(send/recv)

    4--关闭socket

4.UDP通信

  4.1-UDP服务器

    1--创建服务器端socket

    2--绑定IP地址和端口(bind)

    3--数据收发  recvfrom/sendto

      int recvfrom ( SOCKET s, char FAR* buf, int len, int flags, struct sockaddr FAR* from, int FAR* fromlen );

        s:套接字;

        buf:指向一个缓冲区,用来接收数据;

        len:缓冲区的长度;

        flags:设为0;

        from:指向地址结构体,用来接收发送数据方的地址信息;

        fromlen:调用前须给一个初始值,函数调用后会返回地址结构的大小;

      int sendto ( SOCKET s, const char FAR * buf, int len, int flags, const struct sockaddr FAR * to, int tolen );

        s:套接字;

        buf:指向一个缓冲区,包含将要发送的数据;

        len:指定缓冲区中数据的长度;

        flags:设为0;

        to:可选指针,指定目标套接字的地址;

        tolen:参数to指定的地址的长度;

    4--关闭socket

  4.2-UDP客户端

    1--创建客户端socket

    2--数据收发  sendto/recvfrom

    3--关闭socket

5.IP地址格式和端口格式的转换

  5.1-IP地址格式的转换

    将点分十进制的IP地址转为十六进制的格式:

      unsigned long inet_addr ( const char FAR * cp );

    将IP地址从十六进制转为点分十进制的格式:

      char FAR * inet_ntoa ( struct in_addr in );

  5.2-端口格式的转换

    将本机端口的整数格式转为TCP/IP网络整数格式:

      u_short htons ( u_short hostshort );  //16位

      u_long htonl ( u_long hostlong );  //32位

    将端口的网络整数格式转为本地端口的整数格式:

      u_short ntohs ( u_short netshort );

  5.3-主机名<-->IP地址

    5.3.1主机名转换为IP地址

      函数gethostbyname从主机数据库中获取主机名相对应的IP地址;

      struct hostent FAR * gethostbyname ( const char FAR * name );

        name:指向一个主机名字符串;

      返回值:函数返回hostent结构体类型的指针,该结构体类型的定义如下:

        struct hostent {

            char FAR *       h_name;

            char FAR * FAR * h_aliases;

            short            h_addrtype;

            short            h_length;

            char FAR * FAR * h_addr_list;

        };

        该结构体的最后一个成员h_addr_list是一个指针数组,它的每个元素都是一个字符指针,指向内存中存放的一个个点分十进制表示的主机IP地址,一台主机可能会有多个IP地址;

    5.3.2IP地址转换为主机名

      函数gethostbyaddr将根据指定的IP地址获取相应的主机信息;

      struct HOSTENT FAR * gethostbyaddr (

          const char FAR * addr, 

          int len,               

          int type               

      );

          addr:是一个指向点分十进制类型的IP地址的指针;

          len:地址长度;对于AF_INET地址族,长度必须为4个字节;

          type:地址类型,Windows平台下必须设为AF_INET;

      返回值:函数也是返回hostent结构体类型的指针,结构体中的h_name数据成员就是主机名;

 

以上是关于使用基本的socket函数的主要内容,如果未能解决你的问题,请参考以下文章

Linux Socket - 基本socket链接

C/S程序的一般流程和基本socket函数

Linux下socket编程基本知识

socket 的recv函数返回0应该怎样处理

Python网络编程之socket应用

PHP Socket实现websocket基本函数介绍