• c++的socket编程 tcp


    首先看一下要用到的一些函数

    1、创建套接字 socket()

           #include <sys/socket.h>
    int socket(int domain, int type, int protocol);
    domain:
    Name Purpose Man page AF_UNIX, AF_LOCAL Local communication unix(
    7) AF_INET IPv4 Internet protocols ip(7) AF_INET6 IPv6 Internet protocols ipv6(7) AF_IPX IPX - Novell protocols AF_NETLINK Kernel user interface device netlink(7) AF_X25 ITU-T X.25 / ISO-8208 protocol x25(7) AF_AX25 Amateur radio AX.25 protocol AF_ATMPVC Access to raw ATM PVCs AF_APPLETALK AppleTalk ddp(7) AF_PACKET Low level packet interface packet(7) AF_ALG Interface to kernel crypto API
    type: 连接类型
    SOCK_STREAM Provides sequenced, reliable, two-way, connection- based byte streams. An out-of-band data transmission mechanism may be supported. SOCK_DGRAM Supports datagrams (connectionless, unreliable mes‐ sages of a fixed maximum length). SOCK_SEQPACKET Provides a sequenced, reliable, two-way connection- based data transmission path for datagrams of fixed maximum length; a consumer is required to read an entire packet with each input system call. SOCK_RAW Provides raw network protocol access. SOCK_RDM Provides a reliable datagram layer that does not guar‐ antee ordering. SOCK_PACKET Obsolete and should not be used in new programs; see packet(7).

    protocol  协议类型

    socket编程有三种,流式套接字(SOCK_STREAM),数据报套接字(SOCK_DGRAM),原始套接字(SOCK_RAW),前两者较常用。基于TCP的socket编程是流式套接字。

    2、将socket绑定到地址 bind()

           int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

    sockfd  是在上个函数socket()中获得的文件描述符

    addr     结构体类型指针 指向地址

               struct sockaddr {
                   sa_family_t sa_family;
                   char        sa_data[14];
               }

    addrlen 长度,是前面那个参数 addr 的长度,一般用sizeof求得

    struct sockaddr_in {
    
      short int sin_family; /* 通信类型 */
    
      unsigned short int sin_port; /* 端口 */
    
      struct in_addr sin_addr; /* Internet 地址 */
    
      unsigned char sin_zero[8]; /* 与sockaddr结构的长度相同*/
    
    };
    struct in_addr {
        in_addr_t s_addr;
    };

     这里使用sockaddr_in 结构体 传参的时候在强制转换为 sockaddr 结构体

    sockaddr_in 是专门用来保存ipv4的结构体 保存ipv6要用 sockaddr_in6

    sin_port  用htons()函数 将主机字节序转化为网络字节序

    3、监听模式等待请求 linsten()

           int listen(int sockfd, int backlog);
    sockfd   文件描述符
    backlog  等待连接队列的最大长度

    4、向服务器发出连接请求 connect()

           int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
    sockfd    文件描述符

    addr     结构体类型指针 指向服务器地址

    addrlen   结构体长度

    5、服务器接收客户端的连接 accpet()

    int accept(int socket,sockaddr * fromaddr,int * addrlen);
    socket    文件描述符

    fromaddr   客户端地址信息

    addrlen   地址结构体长度

    6、发送数据函数 send()

           ssize_t send(int sockfd, const void *buf, size_t len, int flags);

    sockfd  文件描述符

    *buf      发送的数据

    len        发送数据长度

    flags     0

    7、接收数据函数 recv()

           ssize_t recv(int sockfd, void *buf, size_t len, int flags);

    sockfd  文件描述符

    *buf      接收的数据

    len        接收数据长度

    flags     0

    8、数据的读写 readI()  write()

    ssize_t read(int fd, void *buf, size_t nbytes);
    ssize_t write(int fd, const void *buf, size_t nbytes);

    fd    文件描述符

    buf     读写的数据存放指针

    nbytes  写入读出的数据字节数

    9、关闭套接字 closesocket()

    int closesocket(int socket);

    linux:

    服务器:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    
    int main(){
        //创建套接字
        int serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    
        //将套接字和IP、端口绑定
        struct sockaddr_in serv_addr;
        memset(&serv_addr, 0, sizeof(serv_addr));  //每个字节都用0填充
        serv_addr.sin_family = AF_INET;  //使用IPv4地址
        serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");  //具体的IP地址
        serv_addr.sin_port = htons(1234);  //端口
        bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
    
        //进入监听状态,等待用户发起请求
        listen(serv_sock, 20);
    
        //接收客户端请求
        struct sockaddr_in clnt_addr;
        socklen_t clnt_addr_size = sizeof(clnt_addr);
        int clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);
    
        //向客户端发送数据
        char str[] = "hello world";
        write(clnt_sock, str, sizeof(str));
       
        //关闭套接字
        close(clnt_sock);
        close(serv_sock);
    
        return 0;
    }

    客户端:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>
    int main(){
        //创建套接字
        int sock = socket(AF_INET, SOCK_STREAM, 0);
        //向服务器(特定的IP和端口)发起请求
        struct sockaddr_in serv_addr;
        memset(&serv_addr, 0, sizeof(serv_addr));  //每个字节都用0填充
        serv_addr.sin_family = AF_INET;  //使用IPv4地址
        serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");  //具体的IP地址
        serv_addr.sin_port = htons(1234);  //端口
        connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
       
        //读取服务器传回的数据
        char buffer[40];
        read(sock, buffer, sizeof(buffer)-1);
       
        printf("Message form server: %s
    ", buffer);
       
        //关闭套接字
        close(sock);
        return 0;
    }

    windows:

    服务器:

    #include <stdio.h>
    #include <winsock2.h>
    #pragma comment (lib, "ws2_32.lib")  //加载 ws2_32.dll
    int main(){
        //初始化 DLL
        WSADATA wsaData;
        WSAStartup( MAKEWORD(2, 2), &wsaData);
        //创建套接字
        SOCKET servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
        //绑定套接字
        sockaddr_in sockAddr;
        memset(&sockAddr, 0, sizeof(sockAddr));  //每个字节都用0填充
        sockAddr.sin_family = PF_INET;  //使用IPv4地址
        sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");  //具体的IP地址
        sockAddr.sin_port = htons(1234);  //端口
        bind(servSock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));
        //进入监听状态
        listen(servSock, 20);
        //接收客户端请求
        SOCKADDR clntAddr;
        int nSize = sizeof(SOCKADDR);
        SOCKET clntSock = accept(servSock, (SOCKADDR*)&clntAddr, &nSize);
        //向客户端发送数据
        char *str = "Hello World!";
        send(clntSock, str, strlen(str)+sizeof(char), NULL);
        //关闭套接字
        closesocket(clntSock);
        closesocket(servSock);
        //终止 DLL 的使用
        WSACleanup();
        return 0;
    }

    客户端:

    #include <stdio.h>
    #include <stdlib.h>
    #include <WinSock2.h>
    #pragma comment(lib, "ws2_32.lib")  //加载 ws2_32.dll
    int main(){
        //初始化DLL
        WSADATA wsaData;
        WSAStartup(MAKEWORD(2, 2), &wsaData);
        //创建套接字
        SOCKET sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
        //向服务器发起请求
        sockaddr_in sockAddr;
        memset(&sockAddr, 0, sizeof(sockAddr));  //每个字节都用0填充
        sockAddr.sin_family = PF_INET;
        sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
        sockAddr.sin_port = htons(1234);
        connect(sock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));
        //接收服务器传回的数据
        char szBuffer[MAXBYTE] = {0};
        recv(sock, szBuffer, MAXBYTE, NULL);
        //输出接收到的数据
        printf("Message form server: %s
    ", szBuffer);
        //关闭套接字
        closesocket(sock);
        //终止使用 DLL
        WSACleanup();
        system("pause");
        return 0;
    }
    nbytes
  • 相关阅读:
    屏幕的真实分辨率大小
    CCConfiguration::sharedConfiguration()->loadConfigFile cocos2d-x 中文乱码问题及国际化解决方案
    git 放弃提交到提交之前
    cocos2d-x 输出debug信息
    Ubuntu设置环境变量
    有时候需要统计手机的型号和版本号,利用程序可以获取到相应的手机信息.
    读取 android sys/下的信息
    android 读取 raw 中的文件。
    C/C++中结构体(struct)
    异步图片下载引擎(升级版——ExecutorService+handler)
  • 原文地址:https://www.cnblogs.com/qifeng1024/p/12692311.html
Copyright © 2020-2023  润新知