socket C/C++编程(6)server之accept()函数创建新socket以单独读取缓存区某个client的连接信息(客户端的IP和端口,但是,不包括client端键入的数据)

1. 首先
第一类服务器socket是用于绑定某个服务器端口,第二类服务器socket用于绑定交互(读写)某个listen()缓冲区的client。

2. 代码
accept()函数创建新socket以单独读取缓存区某个client的连接信息(IP和端口,不包括客户端编辑发送的数据)。第二类读取某个client交互信息的socket不关闭的代码如下,

#ifdef WIN32
    #include <windows.h>
#else
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <arpa/inet.h>
#endif
#include <stdio.h>


int main(int argc, char *argv[]){

    // 初始化”ws2_32.lib”
    #ifdef WIN32
        WSADATA ws;
        WSAStartup(MAKEWORD(2,2), &ws);
    #endif

    // 创建socket
    int sock = socket(AF_INET,SOCK_STREAM,0);
    if(sock == -1){
        printf("create sock error!\n");
        return -1;
    }

    // TCP Server指定端口并设置服务端端口的属性,返回(sockaddr*)&saddr

    unsigned short port = 8080; // 默认端口号
    if(argc > 1){
        port = atoi(argv[1]);
    }
    sockaddr_in saddr; // 声明端口
    saddr.sin_family = AF_INET; // TCPIP协议
    saddr.sin_port = htons(port); // 绑定端口号, htons()之host-to-network
    saddr.sin_addr.s_addr = 0; //或htonl(0) 服务器接受的IP地址 0表示接受任意内外网IP

    // 绑定端口到指定的socket,输入(sockaddr*)&saddr
    if(bind(sock, (sockaddr*)&saddr, sizeof(saddr))!=0){
        printf("OS bind socks to this port %d failed\n", port);
        return -2;
    }
    printf("OS bind this port %d to sockets successfully!\n", port);
    listen(sock, 10); // 允许用户连接函数(客户socket(一个客户一个socket),最大请求数队列的长度,)

    int client = accept(sock,0 ,0);
    printf("accept client %d", client);


    getchar();
    return 0;
}

客户端连接之后,如下图,

这里写图片描述

服务器端显示client id(4是缓冲区clients编号的初始值,0到3是错误返回参数),如下图,

这里写图片描述

3. 代码
第二类读取某个client交互信息的socket关闭之后的代码如下,

#ifdef WIN32
    #include <windows.h>
#else
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <arpa/inet.h>
#endif
#include <stdio.h>


int main(int argc, char *argv[]){

    // 初始化”ws2_32.lib”
    #ifdef WIN32
        WSADATA ws;
        WSAStartup(MAKEWORD(2,2), &ws);
    #endif

    // 创建第一类socket
    int sock = socket(AF_INET,SOCK_STREAM,0);
    if(sock == -1){
        printf("create sock error!\n");
        return -1;
    }

    // TCP Server指定端口并设置服务端端口的属性,返回(sockaddr*)&saddr

    unsigned short port = 8080; // 默认端口号
    if(argc > 1){
        port = atoi(argv[1]);
    }
    sockaddr_in saddr; // 声明端口
    saddr.sin_family = AF_INET; // TCPIP协议
    saddr.sin_port = htons(port); // 绑定端口号, htons()之host-to-network
    saddr.sin_addr.s_addr = 0; //或htonl(0) 服务器接受的IP地址 0表示接受任意内外网IP

    // 绑定端口到指定的socket,输入(sockaddr*)&saddr
    if(bind(sock, (sockaddr*)&saddr, sizeof(saddr))!=0){
        printf("OS bind socks to this port %d failed\n", port);
        return -2;
    }
    printf("OS bind this port %d to sockets successfully!\n", port);
    listen(sock, 10); // 允许用户连接函数(客户socket(一个客户一个socket),最大请求数队列的长度,)

    int client = accept(sock,0 ,0); // 第二类socket: 创建一个socket专门读取缓冲区clients(这里缓冲区大小如上行listen代码所示为10)
    printf("accept client %d", client);

    #ifdef WIN32 // 读取数据的第二类socket创建后要记得关闭
        closesocket(client);
    #else
        close(client);       
    #endif

    //#ifdef WIN32 // 端口的第一类socket,不再交互后也要记得关闭,先二后一时堆栈思想
    //  closesocket(sock);
    //#else
    //    close(sock);       
    //#endif



    getchar();
    return 0;
}

客户端成功访问之后(client被服务器从缓冲区读取了),然后,被服务器端断掉socket连接,如下图,

这里写图片描述

该客户端如果需要再进入server之listen()函数的缓冲区,则需要再连接telnet一次。

4. 代码
服务器通过sockaddr_in结构体读取客户端信息,代码如下,

#ifdef WIN32
    #include <windows.h>
#else
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <arpa/inet.h>
#endif
#include <stdio.h>


int main(int argc, char *argv[]){

    // 初始化”ws2_32.lib”
    #ifdef WIN32
        WSADATA ws;
        WSAStartup(MAKEWORD(2,2), &ws);
    #endif

    // 创建第一类socket
    int sock = socket(AF_INET,SOCK_STREAM,0);
    if(sock == -1){
        printf("create sock error!\n");
        return -1;
    }

    // TCP Server指定端口并设置服务端端口的属性,返回(sockaddr*)&saddr

    unsigned short port = 8080; // 默认端口号
    if(argc > 1){
        port = atoi(argv[1]);
    }
    sockaddr_in saddr; // 声明端口
    saddr.sin_family = AF_INET; // TCPIP协议
    saddr.sin_port = htons(port); // 绑定端口号, htons()之host-to-network
    saddr.sin_addr.s_addr = 0; //或htonl(0) 服务器接受的IP地址 0表示接受任意内外网IP

    // 绑定端口到指定的socket,输入(sockaddr*)&saddr
    if(bind(sock, (sockaddr*)&saddr, sizeof(saddr))!=0){
        printf("OS bind socks to this port %d failed\n", port);
        return -2;
    }
    printf("OS bind this port %d to sockets successfully!\n", port);
    listen(sock, 10); // 允许用户连接函数(客户socket(一个客户一个socket),最大请求数队列的长度,)

    sockaddr_in caddr; // 结构体:存储客户端的相关信息:端口号和IP地址s
    socklen_t len = sizeof(caddr); 

    int client = accept(sock,(sockaddr*)&caddr,&len); // 第二类socket: 创建一个socket专门读取缓冲区clients(这里缓冲区大小如上行listen代码所示为10)
    printf("accept client %d", client);
    char *ip = inet_ntoa(caddr.sin_addr); // 客户端IP地址转字符串
    unsigned short cport = ntohs(caddr.sin_port);// 客户端端口号(网络字节序转本地字节序)
    printf("client ip: %s, port is %d\n", ip, cport); // 打印客户端连接信息


    #ifdef WIN32 // 读取数据的第二类socket创建后要记得关闭
        closesocket(client);
    #else
        close(client);       
    #endif

    //#ifdef WIN32 // 端口的第一类socket,不再交互后也要记得关闭,先二后一是堆栈思想
    //  closesocket(sock);
    //#else
    //    close(sock);       
    //#endif



    getchar();
    return 0;
}

成功读取客户端的ip, 端口号,如下,

这里写图片描述

但是,目前我们还无法获取客户端发送的数据,下一步用recv()/read()解决。

参考
http://blog.csdn.net/david_xtd/article/details/7087843

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值