最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c++ - Which functions can be used to send SCTP data, and how do they differ? - Stack Overflow

programmeradmin2浏览0评论

It appear there are very many functions that can send SCTP data on Linux, including general functions such as send() and write() but also sctp_send and sctp_sendmsg. The latter enable some "special SCTP functionality". But how many different functions are there, and how do they differ?

I've got an existing codebase that contains a sctp_recvmsg call:

    int flags = 0;
    sctp_sndrcvinfo zeroed { 0 };
    struct {
            uint32_t frame_nr;
            uint16_t sample_rate;
            uint16_t num_samples;
            uint8_t samples[1500];
    } buffer;
    int result = sctp_recvmsg(sock,
            &buffer, sizeof(buffer), // Actual data
            nullptr, 0, // We don't care about the sender
            &zeroed, // SCTP Metadata
            &flags); // Must be zero before call
     if (result <= 0) // Not good.
     {
        std::cout << "sctp_recvmsg() error " << errno << std::endl;
     }

This successfully receives messages from a closed-source device. I'm trying to build a simulator that sends the same type of SCTP messages. I can successfully connect the socket, but after that the transmission of data fails.

#include <iostream>

#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/sctp.h>
#include <unistd.h>
#include <arpa/inet.h>

struct {
            uint32_t frame_nr;
            uint16_t sample_rate;
            uint16_t num_samples;
            uint8_t samples[1500];
} buffer {0};

int main()
{
        // SCTP server-side setup
        int ls = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP);
        if (ls == -1) {
                perror("failure opening listen socket");
                exit(-3);
        }
        struct sockaddr_in serverAddress { AF_INET };
        serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
        serverAddress.sin_port = htons(19000);

    int br = bind(ls, (struct sockaddr *)&serverAddress, sizeof(serverAddress));
    if (br == -1) {
            perror("bind error");
            close(ls);
            exit(-4);
    }

    // Set up 2 streams.
    struct sctp_initmsg initMsg { 0 };
    initMsg.sinit_num_ostreams = 2; // Matches receiver
    initMsg.sinit_max_instreams = 2; // Matches receiver
    initMsg.sinit_max_attempts = 0;
    initMsg.sinit_max_init_timeo = 0;
    setsockopt(ls, IPPROTO_SCTP, SCTP_INITMSG, &initMsg, sizeof(initMsg));

    int rl = listen(ls, 1);
    if(rl < 0) {
            perror("failed to listen for connection");
            close(ls);
            exit(-5);
    }

    struct sockaddr_in recv_addr;
    socklen_t len = sizeof(recv_addr);
    int ss = accept(ls, reinterpret_cast<struct sockaddr *>(&recv_addr), &len);
    if (ss == -1) {
            perror("failed to accept connection");
            close(ls);
            exit(-6);
    }
    std::cout << "Accepted incoming connection" << std::endl;
    // Attempt 1. Causes ENOENT in receiver (undocumented error code)
    // send(ss, &buffer, sizeof(buffer), 0); // Note: last msg is same size, but not all samples are meaningful.

    // Attempt 2. Causes EINVAL in receiver (another undocumented error code)
    // sctp_sendmsg(ss, &buffer, sizeof(buffer),
    //      NULL, 0, // Do not override destination address
    //      0,0,0,0,0); // No other special options or fields.

    // Attempt 3: plain old write. Also causes EINVAL.
    write(ss, &buffer, sizeof(buffer));
}

Just to be clear: the existing codebase with the sctp_recvmsg can't change. I have to write code to work with that. The part that's under my control is the sending code, and that's the bit for which I've added the MCVE. What SCTP send function should that use, and why? (Bonus Q: why do the other ways to send data cause these errors on the receiver side?)

发布评论

评论列表(0)

  1. 暂无评论