LINUX.ORG.RU

История изменений

Исправление www_linux_org_ru, (текущая версия) :

В крестах нельзя это «покрасивее» переписать и тебе об этом сказали. Опять же - ты бы хоть погуглить о чём вообще речь. Ну это такое.

гыгыгы

анонимус думает, что я не знаю, что такое designated initializer

далее, в принципе можно, но в случае *именно* что sockaddr_in я не уверен

короче смотри код и обрати внимание на то, что:

1. перед sin_family и товарищи старпёрского префикса нет — т.е. все точно как в designated initializer-ах (хотя и это в общем-то похрен, поскольку в хедере)

2. вообще все до /// end of unix_syscall.hpp можно пропустить, т.к. это тонкая обертка, а настоящий код внизу и легко читабелен для сишника

3. царские ошибки я НЕ исправляю, просто переписываю покрасивше с сохранением семантики

4. можно еще покрасивее написать, но надо уж что-то выкатить

#include <sys/mman.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <unistd.h>
#include <sched.h>
#include <stdexcept>
#include <string.h>
#include <thread>
#include <arpa/inet.h>
#include <sys/fcntl.h>

bool logging = true;

/// start of unix_syscall.hpp --- тонкая обертка над сисколлами и структурами ядра

struct SockAddrInet: public sockaddr_in /// за правильность этой структуры я не ручаюсь
{
    SockAddrInet( in_addr_t address, uint16_t port )
    {
        sin_family      = AF_INET;
        sin_port        = htons(port);
        sin_addr.s_addr = htonl(address);
    }
};

int safe_call(int value, int line, const char* ctx)
{
    std::string message = std::to_string(line) + " " + std::string(ctx)  +  " == " + std::to_string(value);

    if(value == -1) {
        message += ", errno(" + std::to_string(errno) + ") == " + strerror(errno) ;
        throw std::runtime_error(message);
    }else{
        if( logging )
            fprintf(stderr, "safe_call success: %s\n", message.c_str());
    }
    return value;
}

#define verbose_safe_call(call) safe_call(call, __LINE__, #call)

#define accept(a,b,c)         verbose_safe_call(accept(a,b,c))
#define bind(a,b,c)           verbose_safe_call(bind(a,b,c))
#define listen(a,b)           verbose_safe_call(listen(a,b))
#define read(a,b,c)           verbose_safe_call(read(a,b,c))
#define socket(a,b,c)         verbose_safe_call(socket(a,b,c))
#define setsockopt(a,b,c,d,e) verbose_safe_call(setsockopt(a,b,c,d,e))
#define write(a,b,c)          verbose_safe_call(write(a,b,c))

/// end of unix_syscall.hpp

void worker(int listen_fd, int id)
{
    fprintf( stderr, "start thread(%lu)\n", id );

    while( int accept_fd = accept(listen_fd, nullptr, nullptr) )
    {
        uint64_t buffer[(1024 * 10) / sizeof(uint64_t)];
        read(accept_fd, buffer, sizeof(uint64_t));
        for(auto & x : buffer) x = buffer[0];

        for( auto ptr = std::begin(buffer); ptr < std::end(buffer); ptr += 1024/sizeof(uint64_t) )
        {
            write(accept_fd, ptr, 1024); /// это говнокод, но я тут сохраняю ошибки царя
        }
        close(accept_fd);
        sleep(10); /// и это тоже говнокод, но я тут тоже сохраняю ошибки царя
    }
}

int listen_to(in_addr_t addr, uint16_t port)
{
    const size_t n = 100;
    auto saddr     = SockAddrInet(addr, port);
    auto listen_fd = socket( AF_INET, SOCK_STREAM, 0 );
    int  option    = 1;
    setsockopt( listen_fd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option) );
    bind( listen_fd, (__CONST_SOCKADDR_ARG)&saddr, sizeof(saddr) );
    listen( listen_fd, n );
    return listen_fd;
}

int main()
{
    int listen_fd = listen_to(INADDR_LOOPBACK, 8883);
    const int n=10;

    worker( listen_fd, 0 ); return 0; /// строка для однопоточного теста; для тредов -- закомментить

    std::thread threads[n];

    for(int id=0; id<n; ++id )
    {
        threads[id] = std::thread( worker, listen_fd, id );
    }

    return 0;
}

да, как это тестить:

user@host $ nc 127.0.0.1 8883
abcd<этнер>

выхлоп сервера:

safe_call success: 77 socket(2,SOCK_STREAM,0) == 3
safe_call success: 79 setsockopt(listen_fd,1,2,&option,sizeof(option)) == 0
safe_call success: 80 bind(listen_fd,(__const struct sockaddr *)&saddr,sizeof(saddr)) == 0
safe_call success: 81 listen(listen_fd,n) == 0
start thread(0)
safe_call success: 58 accept(listen_fd,nullptr,nullptr) == 4
safe_call success: 61 read(accept_fd,buffer,sizeof(uint64_t)) == 5
safe_call success: 66 write(accept_fd,ptr,1024) == 1024
safe_call success: 66 write(accept_fd,ptr,1024) == 1024
safe_call success: 66 write(accept_fd,ptr,1024) == 1024
safe_call success: 66 write(accept_fd,ptr,1024) == 1024
safe_call success: 66 write(accept_fd,ptr,1024) == 1024
safe_call success: 66 write(accept_fd,ptr,1024) == 1024
safe_call success: 66 write(accept_fd,ptr,1024) == 1024
safe_call success: 66 write(accept_fd,ptr,1024) == 1024
safe_call success: 66 write(accept_fd,ptr,1024) == 1024
safe_call success: 66 write(accept_fd,ptr,1024) == 1024

я компилял и пускал это под 32 битами

Исправление www_linux_org_ru, :

В крестах нельзя это «покрасивее» переписать и тебе об этом сказали. Опять же - ты бы хоть погуглить о чём вообще речь. Ну это такое.

гыгыгы

анонимус думает, что я не знаю, что такое designated initializer

далее, в принципе можно, но в случае *именно* что sockaddr_in я не уверен

короче смотри код и обрати внимание на то, что:

1. перед sin_family и товарищи старпёрского префикса нет — т.е. все точно как в designated initializer-ах (хотя и это в общем-то похрен, поскольку в хедере)

2. вообще все до /// end of unix_syscall.hpp можно пропустить, т.к. это тонкая обертка, а настоящий код внизу и легко читабелен для сишника

3. царские ошибки я НЕ исправляю, просто переписываю покрасивше с сохранением семантики

4. можно еще покрасивее написать, но надо уж что-то выкатить

#include <sys/mman.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <unistd.h>
#include <sched.h>
#include <stdexcept>
#include <string.h>
#include <thread>
#include <arpa/inet.h>
#include <sys/fcntl.h>

bool logging = true;

/// start of unix_syscall.hpp --- тонкая обертка над сисколлами и структурами ядра

struct SockAddrInet: public sockaddr_in /// за правильность этой структуры я не ручаюсь
{
    SockAddrInet( in_addr_t address, uint16_t port )
    {
        sin_family      = AF_INET;
        sin_port        = htons(port);
        sin_addr.s_addr = htonl(address);
    }
};

int safe_call(int value, int line, const char* ctx)
{
    std::string message = std::to_string(line) + " " + std::string(ctx)  +  " == " + std::to_string(value);

    if(value == -1) {
        message += ", errno(" + std::to_string(errno) + ") == " + strerror(errno) ;
        throw std::runtime_error(message);
    }else{
        if( logging )
            fprintf(stderr, "safe_call success: %s\n", message.c_str());
    }
    return value;
}

#define verbose_safe_call(call) safe_call(call, __LINE__, #call)

#define accept(a,b,c)         verbose_safe_call(accept(a,b,c))
#define bind(a,b,c)           verbose_safe_call(bind(a,b,c))
#define listen(a,b)           verbose_safe_call(listen(a,b))
#define read(a,b,c)           verbose_safe_call(read(a,b,c))
#define socket(a,b,c)         verbose_safe_call(socket(a,b,c))
#define setsockopt(a,b,c,d,e) verbose_safe_call(setsockopt(a,b,c,d,e))
#define write(a,b,c)          verbose_safe_call(write(a,b,c))

/// end of unix_syscall.hpp

void worker(int listen_fd, int id)
{
    fprintf( stderr, "start thread(%lu)\n", id );

    while( int accept_fd = accept(listen_fd, nullptr, nullptr) )
    {
        uint64_t buffer[(1024 * 10) / sizeof(uint64_t)];
        read(accept_fd, buffer, sizeof(uint64_t));
        for(auto & x : buffer) x = buffer[0];

        for( auto ptr = std::begin(buffer); ptr < std::end(buffer); ptr += 1024/sizeof(uint64_t) )
        {
            write(accept_fd, ptr, 1024); /// это говнокод, но я тут сохраняю ошибки царя
        }
        close(accept_fd);
        sleep(10); /// и это тоже говнокод, но я тут тоже сохраняю ошибки царя
    }
}

int listen_to(in_addr_t addr, uint16_t port)
{
    const size_t n = 100;
    auto saddr     = SockAddrInet(addr, port);
    auto listen_fd = socket( AF_INET, SOCK_STREAM, 0 );
    int  option    = 1;
    setsockopt( listen_fd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option) );
    bind( listen_fd, (__CONST_SOCKADDR_ARG)&saddr, sizeof(saddr) );
    listen( listen_fd, n );
    return listen_fd;
}

int main()
{
    int listen_fd = listen_to(INADDR_LOOPBACK, 8883);
    const int n=10;

    worker( listen_fd, 0 ); return 0; /// строка для однопоточного теста; для тредов -- закомментить

    std::thread threads[n];

    for(int id=0; id<n; ++id )
    {
        threads[id] = std::thread( worker, listen_fd, id );
    }

    return 0;
}

да, как это тестить:

nc 127.0.0.1 8883 abcd<этнер>

выхлоп сервера:

safe_call success: 77 socket(2,SOCK_STREAM,0) == 3
safe_call success: 79 setsockopt(listen_fd,1,2,&option,sizeof(option)) == 0
safe_call success: 80 bind(listen_fd,(__const struct sockaddr *)&saddr,sizeof(saddr)) == 0
safe_call success: 81 listen(listen_fd,n) == 0
start thread(0)
safe_call success: 58 accept(listen_fd,nullptr,nullptr) == 4
safe_call success: 61 read(accept_fd,buffer,sizeof(uint64_t)) == 5
safe_call success: 66 write(accept_fd,ptr,1024) == 1024
safe_call success: 66 write(accept_fd,ptr,1024) == 1024
safe_call success: 66 write(accept_fd,ptr,1024) == 1024
safe_call success: 66 write(accept_fd,ptr,1024) == 1024
safe_call success: 66 write(accept_fd,ptr,1024) == 1024
safe_call success: 66 write(accept_fd,ptr,1024) == 1024
safe_call success: 66 write(accept_fd,ptr,1024) == 1024
safe_call success: 66 write(accept_fd,ptr,1024) == 1024
safe_call success: 66 write(accept_fd,ptr,1024) == 1024
safe_call success: 66 write(accept_fd,ptr,1024) == 1024

я компилял и пускал это под 32 битами

Исходная версия www_linux_org_ru, :

В крестах нельзя это «покрасивее» переписать и тебе об этом сказали. Опять же - ты бы хоть погуглить о чём вообще речь. Ну это такое.

гыгыгы

анонимус думает, что я не знаю, что такое designated initializer

далее, в принципе можно, но в случае *именно* что sockaddr_in я не уверен

короче смотри код и обрати внимание на то, что:

1. перед sin_family и товарищи старпёрского префикса нет — т.е. все точно как в designated initializer-ах (хотя и это в общем-то похрен, поскольку в хедере)

2. вообще все до /// end of unix_syscall.hpp можно пропустить, т.к. это тонкая обертка, а настоящий код внизу и легко читабелен для сишника

3. царские ошибки я НЕ исправляю, просто переписываю покрасивше с сохранением семантики

4. можно еще покрасивее написать, но надо уж что-то выкатить

#include <sys/mman.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <unistd.h>
#include <sched.h>
#include <stdexcept>
#include <string.h>
#include <thread>
#include <arpa/inet.h>
#include <sys/fcntl.h>

bool logging = true;

/// start of unix_syscall.hpp --- тонкая обертка над сисколлами и структурами ядра

struct SockAddrInet: public sockaddr_in /// за правильность этой структуры я не ручаюсь
{
    SockAddrInet( in_addr_t address, uint16_t port )
    {
        sin_family      = AF_INET;
        sin_port        = htons(port);
        sin_addr.s_addr = htonl(address);
    }
};

int safe_call(int value, int line, const char* ctx)
{
    std::string message = std::to_string(line) + " " + std::string(ctx)  +  " == " + std::to_string(value);

    if(value == -1) {
        message += ", errno(" + std::to_string(errno) + ") == " + strerror(errno) ;
        throw std::runtime_error(message);
    }else{
        if( logging )
            fprintf(stderr, "safe_call success: %s\n", message.c_str());
    }
    return value;
}

#define verbose_safe_call(call) safe_call(call, __LINE__, #call)

#define accept(a,b,c)         verbose_safe_call(accept(a,b,c))
#define bind(a,b,c)           verbose_safe_call(bind(a,b,c))
#define listen(a,b)           verbose_safe_call(listen(a,b))
#define read(a,b,c)           verbose_safe_call(read(a,b,c))
#define socket(a,b,c)         verbose_safe_call(socket(a,b,c))
#define setsockopt(a,b,c,d,e) verbose_safe_call(setsockopt(a,b,c,d,e))
#define write(a,b,c)          verbose_safe_call(write(a,b,c))

/// end of unix_syscall.hpp

void worker(int listen_fd, int id)
{
    fprintf( stderr, "start thread(%lu)\n", id );

    while( int accept_fd = accept(listen_fd, nullptr, nullptr) )
    {
        uint64_t buffer[(1024 * 10) / sizeof(uint64_t)];
        read(accept_fd, buffer, sizeof(uint64_t));
        for(auto & x : buffer) x = buffer[0];

        for( auto ptr = std::begin(buffer); ptr < std::end(buffer); ptr += 1024/sizeof(uint64_t) )
        {
            write(accept_fd, ptr, 1024); /// это говнокод, но я тут сохраняю ошибки царя
        }
        close(accept_fd);
        sleep(10); /// и это тоже говнокод, но я тут тоже сохраняю ошибки царя
    }
}

int listen_to(in_addr_t addr, uint16_t port)
{
    const size_t n = 100;
    auto saddr     = SockAddrInet(addr, port);
    auto listen_fd = socket( AF_INET, SOCK_STREAM, 0 );
    int  option    = 1;
    setsockopt( listen_fd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option) );
    bind( listen_fd, (__CONST_SOCKADDR_ARG)&saddr, sizeof(saddr) );
    listen( listen_fd, n );
    return listen_fd;
}

int main()
{
    int listen_fd = listen_to(INADDR_LOOPBACK, 8883);
    const int n=10;

    worker( listen_fd, 0 ); return 0; /// строка для однопоточного теста; для тредов -- закомментить

    std::thread threads[n];

    for(int id=0; id<n; ++id )
    {
        threads[id] = std::thread( worker, listen_fd, id );
    }

    return 0;
}