linux socket


#include <sys/socket.h>
#include <sys/types.h>
#include <sys/select.h>

#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>

#include <stdio.h>
#include <iostream>
using namespace std;

// uint32_t htonl(uint32_t hostlong);
// 将32位的数据从主机字节序转换为网络字节序
// in_addr.saddr = htonl(INADDR_ANY)

// uint16_t htons(uint16_t hostshort);
// 将16位的数据从主机字节序转换为网络字节序

// uint32_t ntohl(uint32_t netlong);
// 将32位的数据从网络字节序转换为主机字节序

// uint16_t ntohs(uint16_t netshort);
// 将16位的数据从网络字节序转换为主机字节序

#define MAX_CLIENT_COUNT 16

struct Client_Socket_IPPort {
    int hSocket;
    uint32_t uIPAddress;
    uint16_t uPort;
};

void printhost(struct hostent *host)
{
    char **aliases = NULL;
    char **addr_list = NULL;
    char addr_p[INET_ADDRSTRLEN];   // IPv4

    /* print host name and aliases */
    printf("hostname: %s\n", host->h_name);
    for(aliases = host->h_aliases; *aliases; aliases++)
    {
        printf("alternate name: %s\n", *aliases);
    }

    /* print address type and length */
    if(host->h_addrtype == AF_INET)
    {
        printf("address type: AF_INET\n");
    }
    else
    {
        printf("Not an IPv4 address.\n");
    }
    printf("address length: %d\n", host->h_length);

    /* print address list */
    printf("%x\n", *(int *)(*(host->h_addr_list)));
    for(addr_list = host->h_addr_list; *addr_list; addr_list++)
    {
        printf("address: %s\n", inet_ntop(host->h_addrtype, *addr_list, addr_p, INET_ADDRSTRLEN));
    }
}

void printclient(Client_Socket_IPPort client[]) {
    cout << "client list: " << endl;
    int nIndex = 0;
    for (int i=0; i<MAX_CLIENT_COUNT; i++) {
        if (client[i].hSocket <= 0) {
            continue;
        }
        cout << nIndex << ": ip address: ";
        uint32_t uClientIPAddress = client[i].uIPAddress;
        cout << ((uClientIPAddress & 0xff000000) >> 24);
        cout << ".";
        cout << ((uClientIPAddress & 0x00ff0000) >> 16);
        cout << ".";
        cout << ((uClientIPAddress & 0x0000ff00) >> 8);
        cout << ".";
        cout << ((uClientIPAddress & 0x000000ff) >> 0);
        cout << ", port: ";
        cout << client[i].uPort << endl;
        nIndex++;
    }
    cout << endl;
}

int mainServer() {

    // 1: gethostent
    cout << "1: gethostent" << endl;
    sethostent(1);
    struct hostent * host = NULL;
    while ((host = gethostent()) != 0)
    {
        printhost(host);
        cout << endl;
    }
    endhostent();

    // 2: port
    int nPort = 0;
    cout << "2: please enter ip and port: ";
    cin >> nPort;
    cout << endl;

    // 3: socket
    cout << "3: socket" << endl;
    int hServer = socket(AF_INET, SOCK_STREAM, 0);
    if (hServer == -1) {
        cout << "socket error" << endl;
        return 1;
    } else {
        cout << "socket success" << endl;
    }
    cout << endl;

    // 4: setsockopt
    cout << "4: setsockopt" << endl;
    int yes = 1;
    if (setsockopt(hServer, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
        cout << "setsockopt error" << endl;
    } else {
        cout << "setsockopt success" << endl;
    }
    cout << endl;

    // 5: bind
    cout << "5: bind" << endl;
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(nPort);
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    int nBind = bind(hServer, (struct sockaddr *)&server_addr, sizeof(server_addr));
    if (nBind == -1) {
        cout << "bind error" << endl;
        return 1;
    } else  {
        cout << "bind success" << endl;
    }
    cout << endl;

    // 6: listen
    cout << "6: listen: ";
    if (listen(hServer, MAX_CLIENT_COUNT) == -1) {
        cout << "listen error " << endl;
        return 1;
    } else {
        cout << "listen success" << endl;
    }
    cout << endl;

    // client数组
    Client_Socket_IPPort hClient[MAX_CLIENT_COUNT] = {0};
    for (int i=0; i<MAX_CLIENT_COUNT; i++) {
        hClient[i].hSocket = 0;
    }

    unsigned char cRecv[1024] = {0};
    fd_set f;
    struct timeval t;
    t.tv_sec = 10;
    t.tv_usec = 0;

    while (1) {
        // 将指定的文件描述符集清空
        FD_ZERO(&f);

        // 将hServer加入f集合
        if (!FD_ISSET(hServer, &f))
            FD_SET(hServer, &f);

        // 将现有client加入f集合
        for (int i = 0; i < MAX_CLIENT_COUNT; i++) {
            if (hClient[i].hSocket != 0) {
                if (!FD_ISSET(hClient[i].hSocket, &f))
                    FD_SET(hClient[i].hSocket, &f);
            }
        }

        // 最大文件描述符
        int nMaxnfds = hServer;
        for (int i=0; i<MAX_CLIENT_COUNT; i++) {
            if (nMaxnfds < hClient[i].hSocket) {
                nMaxnfds = hClient[i].hSocket;
            }
        }
        nMaxnfds++;

        // select
        int nSelect = select(nMaxnfds, &f, NULL, NULL, &t);
        if (nSelect < 0) {
            cout << "select error" << endl;
            break;
        } else if (nSelect == 0) {
        }

        // new connection
        if (FD_ISSET(hServer, &f)) {
            cout << "accept client: " << endl;
            struct sockaddr_in client_addr;
            socklen_t length = sizeof(client_addr);
            int hAcceptClient = accept(hServer, (struct sockaddr*)&client_addr, &length);
            if (hAcceptClient < 0) {
                cout << "accept error" << endl;
                return 1;
            } else {
                cout << "accept success" << endl;
            }

            for (int i=0; i<MAX_CLIENT_COUNT; i++) {
                if (hClient[i].hSocket == 0) {
                    hClient[i].hSocket = hAcceptClient;
                    hClient[i].uIPAddress = ntohl(client_addr.sin_addr.s_addr);
                    hClient[i].uPort = ntohs(client_addr.sin_port);
                    break;
                }
            }
            printclient(hClient);
        }

        // recv
        for (int i=0; i<MAX_CLIENT_COUNT; i++) {
            if (hClient[i].hSocket <= 0) {
                continue;
            }
            if (FD_ISSET(hClient[i].hSocket, &f)) {
                int nRecvLength = recv(hClient[i].hSocket, cRecv, sizeof(cRecv), 0);

                // connect drop
                if (nRecvLength <= 0) {
                    close(hClient[i].hSocket);
                    FD_CLR(hClient[i].hSocket, &f);
                    hClient[i].hSocket = 0;
                    printclient(hClient);
                } else {
                    sockaddr_in recvClient;
                    recvClient.sin_addr.s_addr = htonl(hClient[i].uIPAddress);
                    printf("recv from %s:%d", inet_ntoa(recvClient.sin_addr), hClient[i].uPort);
                    for (int j=0; j<nRecvLength; j++) {
                        printf(" 0x%02x ", cRecv[j]);
                    }
                    cout << endl;
                }
            }
        }
    }

    // close
    cout << "close" << endl;
    for (int i=0; i<MAX_CLIENT_COUNT; i++) {
        if (hClient[i].hSocket != 0) {
            close(hClient[i].hSocket);
        }
    }
    close(hServer);

    return 1;
}

int main() {
    return mainServer();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值