объясняет и этот аспект.

рабатывал это простое клиент-серверное приложение с C, где клиент просто отправляет случайные данные на сервер, а сервер просто слушает то, что отправляет клиент. Я использую протокол SCTP, и мне интересно, как реализовать в нем функцию множественной адресации.

Я искал в интернете информацию о SCTP и множественной адресации и не смог найти примеров того, как дать команду SCTP использовать несколько адресов для связи. Мне удалось найти только те команды, которые нужно использовать при попытке настроить SCTP с множественной адресацией, и это должно быть довольно просто.

Я создал клиента и сервер, которые оба используют мои компьютеры два интерфейса WLAN в качестве своих точек подключения. Оба адаптера подключены к одной и той же точке доступа. Сервер прослушивает данные от клиента с этих интерфейсов, и клиент отправляет данные через них. Проблема заключается в том, что, когда я отключаю основной адаптер WLAN, на который клиент отправляет данные, передача просто останавливается, когда он должен вернуться к дополнительному соединению. Я проследил пакеты с помощью Wireshark, и первые пакеты INIT и INIT_ACK сообщают, что и клиент, и сервер используют адаптеры WLAN в качестве своих каналов связи.

Когда я повторно подключаюсь к первичному WLAN-соединению, передача продолжается через некоторое время и приводит к огромной загрузке пакетов на сервер, что неправильно. Пакеты должны были быть переданы через вторичное соединение. На многих сайтах говорят, что SCTP автоматически переключается между соединениями, но в моем случае этого не происходит. Так у вас, ребята, есть какие-то подсказки, почему передача не возвращается к вторичному соединению, когда первичное соединение не работает, даже если клиент и сервер знают адреса друг друга, включая вторичный адрес?

О сервере:

Сервер создает сокет типа SOCK_SEQPACKET и связывает все интерфейсы, найденные с INADDR_ANY. getladdrs сообщает, что сервер ограничен 3 адресами (включая 127.0.0.1). После этого сервер прослушивает сокет и ждет, пока клиент отправит данные. Сервер читает данные с помощью вызова sctp_recvmsg.

О клиенте:

Клиент также создает сокет SEQPACKET и подключается к IP-адресу, указанному в аргументе командной строки. getladdrs в этом случае возвращает также 3 адреса, как в случае с серверами. После этого клиент просто начинает отправлять данные на сервер с задержкой в ​​одну секунду, пока пользователь не прервет передачу с помощью Ctrl-C.

Вот некоторый исходный код:

Сервер:

#define BUFFER_SIZE (1 << 16)
#define PORT 10000   

int sock, ret, flags;
int i;
int addr_count = 0;
char buffer[BUFFER_SIZE];
socklen_t from_len;

struct sockaddr_in addr;
struct sockaddr_in *laddr[10];
struct sockaddr_in *paddrs[10];
struct sctp_sndrcvinfo sinfo;
struct sctp_event_subscribe event;  
struct sctp_prim prim_addr; 
struct sctp_paddrparams heartbeat;
struct sigaction sig_handler;

void handle_signal(int signum);

int main(void)
{
    if((sock = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP)) < 0)
        perror("socket");

    memset(&addr, 0, sizeof(struct sockaddr_in));
    memset((void*)&event, 1, sizeof(struct sctp_event_subscribe));

    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    addr.sin_port = htons(PORT);

    from_len = (socklen_t)sizeof(struct sockaddr_in);

    sig_handler.sa_handler = handle_signal;
    sig_handler.sa_flags = 0;

    if(sigaction(SIGINT, &sig_handler, NULL) == -1)
        perror("sigaction");

    if(setsockopt(sock, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe)) < 0)
        perror("setsockopt");

    if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int))< 0)
        perror("setsockopt");

    if(bind(sock, (struct sockaddr*)&addr, sizeof(struct sockaddr)) < 0)
        perror("bind");

    if(listen(sock, 2) < 0)
        perror("listen");

    addr_count = sctp_getladdrs(sock, 0, (struct sockaddr**)laddr);
    printf("Addresses binded: %d\n", addr_count);

    for(i = 0; i < addr_count; i++)
         printf("Address %d: %s:%d\n", i +1, inet_ntoa((*laddr)[i].sin_addr), (*laddr)[i].sin_port);

    sctp_freeladdrs((struct sockaddr*)*laddr);

    while(1)
    {
        flags = 0;

        ret = sctp_recvmsg(sock, buffer, BUFFER_SIZE, (struct sockaddr*)&addr, &from_len, NULL, &flags);

        if(flags & MSG_NOTIFICATION)
        printf("Notification received from %s:%u\n",  inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));

        printf("%d bytes received from %s:%u\n", ret, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));      
    }

    if(close(sock) < 0)
        perror("close");
}   

void handle_signal(int signum)
{
    switch(signum)
    {
        case SIGINT:
            if(close(sock) != 0)
                perror("close");
            exit(0);
            break;  
        default: exit(0);
            break;
    }
}

И Клиент:

#define PORT 10000
#define MSG_SIZE 1000
#define NUMBER_OF_MESSAGES 1000
#define PPID 1234

int sock;
struct sockaddr_in *paddrs[10];
struct sockaddr_in *laddrs[10];

void handle_signal(int signum);

int main(int argc, char **argv)
{
    int i;
    int counter = 1;
    int ret;
    int addr_count;
    char address[16];
    char buffer[MSG_SIZE];
    sctp_assoc_t id;
    struct sockaddr_in addr;
    struct sctp_status status;
    struct sctp_initmsg initmsg;
    struct sctp_event_subscribe events;
    struct sigaction sig_handler;

    memset((void*)&buffer,  'j', MSG_SIZE);
    memset((void*)&initmsg, 0, sizeof(initmsg));
    memset((void*)&addr,    0, sizeof(struct sockaddr_in));
    memset((void*)&events, 1, sizeof(struct sctp_event_subscribe));

    if(argc != 2 || (inet_addr(argv[1]) == -1))
    {
        puts("Usage: client [IP ADDRESS in form xxx.xxx.xxx.xxx] ");        
        return 0;
    }

    strncpy(address, argv[1], 15);
    address[15] = 0;

    addr.sin_family = AF_INET;
    inet_aton(address, &(addr.sin_addr));
    addr.sin_port = htons(PORT);

    initmsg.sinit_num_ostreams = 2;
    initmsg.sinit_max_instreams = 2;
    initmsg.sinit_max_attempts = 5;

    sig_handler.sa_handler = handle_signal;
    sig_handler.sa_flags = 0;

    if(sigaction(SIGINT, &sig_handler, NULL) == -1)
        perror("sigaction");

    if((sock = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP)) < 0)
        perror("socket");

    if((setsockopt(sock, SOL_SCTP, SCTP_INITMSG, &initmsg, sizeof(initmsg))) != 0)
        perror("setsockopt");

    if((setsockopt(sock, SOL_SCTP, SCTP_EVENTS, (const void *)&events, sizeof(events))) != 0)
        perror("setsockopt");

    if(sendto(sock, buffer, MSG_SIZE, 0, (struct sockaddr*)&addr, sizeof(struct sockaddr)) == -1)
        perror("sendto");

    addr_count = sctp_getpaddrs(sock, 0, (struct sockaddr**)paddrs);
    printf("\nPeer addresses: %d\n", addr_count);

    for(i = 0; i < addr_count; i++)
    printf("Address %d: %s:%d\n", i +1, inet_ntoa((*paddrs)[i].sin_addr), (*paddrs)[i].sin_port);

    sctp_freepaddrs((struct sockaddr*)*paddrs);

    addr_count = sctp_getladdrs(sock, 0, (struct sockaddr**)laddrs);
    printf("\nLocal addresses: %d\n", addr_count);

    for(i = 0; i < addr_count; i++)
    printf("Address %d: %s:%d\n", i +1, inet_ntoa((*laddrs)[i].sin_addr), (*laddrs)[i].sin_port);

    sctp_freeladdrs((struct sockaddr*)*laddrs);

    i = sizeof(status);
    if((ret = getsockopt(sock, SOL_SCTP, SCTP_STATUS, &status, (socklen_t *)&i)) != 0)
        perror("getsockopt");

    printf("\nSCTP Status:\n--------\n");
    printf("assoc id  = %d\n", status.sstat_assoc_id);
    printf("state     = %d\n", status.sstat_state);
    printf("instrms   = %d\n", status.sstat_instrms);
    printf("outstrms  = %d\n--------\n\n", status.sstat_outstrms);

    for(i = 0; i < NUMBER_OF_MESSAGES; i++)
    {
        counter++;
        printf("Sending data chunk #%d...", counter);
        if((ret = sendto(sock, buffer, MSG_SIZE, 0, (struct sockaddr*)&addr, sizeof(struct sockaddr))) == -1)
            perror("sendto");

        printf("Sent %d bytes to peer\n",ret);

        sleep(1);
    }

    if(close(sock) != 0)
        perror("close");
}


void handle_signal(int signum)
{

    switch(signum)
    {
        case SIGINT:
            if(close(soc,k) != 0)
                perror("close");
            exit(0);
            break;  
        default: exit(0);
            break;
    }

}

Так у вас, ребята, есть какие-то подсказки, что я делаю неправильно?

Ответы на вопрос(3)

Ваш ответ на вопрос