1

我和我的一个朋友正在尝试实现这个简单的客户端-服务器应用程序。我们观察了性能,我们注意到,为了传输 3 个文件,单个 SCTP 关联 3-streamed 的性能远低于 3 个 tcp 连接。研究该理论,我们预计至少有相同的性能,总体而言,因为 SCTP 多流应该减少 tcp 开销。这是服务器:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <net/if.h>
#include <stdlib.h>
#include <time.h>
#include <sys/stat.h>
#include <fcntl.h>

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

int sockCli, sockServ, i, flags, res, scanned;

int one = open("files/first.txt",  O_RDONLY);
int two = open("files/second.txt",  O_RDONLY);
int three = open("files/third.txt",  O_RDONLY);

if(one < 0 || two < 0 || three < 0) {
    printf("Error on opening file\n");
    exit(1);
}

struct sockaddr_in client, server;

struct sctp_initmsg initmsg;

char buffer[1025];

sockServ = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP);

if(sockServ < 0) {
    printf("failed on creating socket\n");
    exit(1);
}

memset(&server, 0, sizeof(server));
memset(&client, 0, sizeof(client));

server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl( INADDR_ANY );
server.sin_port = htons(35000);
int servSize = sizeof(server);

memset( &initmsg, 0, sizeof(initmsg) );
initmsg.sinit_num_ostreams = 3;
initmsg.sinit_max_instreams = 3;
initmsg.sinit_max_attempts = 2;
setsockopt(sockServ, IPPROTO_SCTP, SCTP_INITMSG, &initmsg, sizeof(initmsg) );

res = bind(sockServ, (struct sockaddr *)&server, sizeof(server));

if(res < 0) {
    printf("bind() failed\n");
    exit(1);
}

res = listen(sockServ, 5);

sockCli = accept(sockServ, (struct sockaddr*)&client, (socklen_t*)&servSize);

for(i=0; i<3; i++) {

    memset(buffer, 0, sizeof(buffer));

    if(i==0) {

        while((scanned = read(one, (void*)buffer, sizeof(buffer))) > 0) {
            sctp_sendmsg(sockCli, (void *)buffer, (size_t)strlen(buffer),
                         (struct sockaddr*)&client, (socklen_t)sizeof(client), 0, 0, 0 /* stream */, 0, 0 );
            memset(buffer, 0, sizeof(buffer));
        }

    }


    if(i==1) {

        while((scanned = read(two, (void*)buffer, sizeof(buffer))) > 0) {
            sctp_sendmsg(sockCli, (void *)buffer, (size_t)strlen(buffer),
                    (struct sockaddr*)&client, (socklen_t)sizeof(client), 0, 0, 1 /* stream */, 0, 0 );
            memset(buffer, 0, sizeof(buffer));
        }

    }


    if(i==0) {

        while((scanned = read(three, (void*)buffer, sizeof(buffer))) > 0) {
            sctp_sendmsg(sockCli, (void *)buffer, (size_t)strlen(buffer),
                    (struct sockaddr*)&client, (socklen_t)sizeof(client), 0, 0, 2 /* stream */, 0, 0 );
            memset(buffer, 0, sizeof(buffer));
        }

    }

}

close(sockCli);
close(sockServ);
close(one); close(two); close(three);
return 0;

}

和客户:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <net/if.h>
#include <stdlib.h>
#include <time.h>

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

remove("first.txt");
remove("second.txt");
remove("third.txt");

FILE* files[3];

int i, flags, count0=0, count1=0, count2=0, res, received, sockCli;

struct sockaddr_in server;

struct sctp_sndrcvinfo sndrcvinfo;
struct sctp_event_subscribe events;
struct sctp_initmsg initmsg;

struct timeval begin, end;
int sec, usecs;

char buffer[1025];

char ipServer[32] = "127.0.0.1";
short int servPort = 35000;

sockCli = socket(AF_INET, SOCK_STREAM , IPPROTO_SCTP);

if(sockCli < 0) {
    printf("Error on creating socket\n");
    exit(1);
}

memset(&initmsg, 0, sizeof(initmsg));
initmsg.sinit_num_ostreams = 3;
initmsg.sinit_max_instreams = 3;
initmsg.sinit_max_attempts = 2;
res = setsockopt(sockCli, IPPROTO_SCTP, SCTP_INITMSG, &initmsg, sizeof(initmsg) );

if(res < 0) {
    printf("setsockopt() initmsg failed\n");
    exit(1);
}

memset(&events, 0, sizeof(events));
events.sctp_data_io_event = 1;
res = setsockopt(sockCli, SOL_SCTP, SCTP_EVENTS, (const void *)&events, sizeof(events) );

if(res < 0) {
    printf("setsockopt() events failed\n");
    exit(1);
}


memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
inet_pton(AF_INET, ipServer, &server.sin_addr);
server.sin_port = htons(servPort);
int servSize = sizeof(server);

for(i=0; i<3; i++) {

    if(i==0)
        files[i] = fopen("first.txt", "a+");
    if(i==1)
        files[i] = fopen("second.txt", "a+");
    if(i==2)
        files[i] = fopen("third.txt", "a+");
}

res = connect(sockCli, (struct sockaddr*)&server, sizeof(server));

if(res < 0) {
    printf("connect() failed\n");
    exit(1);
}

gettimeofday(&begin, NULL);

while(1) {

    memset(buffer, 0, sizeof(buffer));
    received = sctp_recvmsg(sockCli, (void*)buffer, sizeof(buffer), (struct sockaddr*)&server, (socklen_t*)&servSize, &sndrcvinfo, &flags);

    if(received == 0) {
        printf("Received 0 bytes, all streams ended\n");
        break;
    }

    if(sndrcvinfo.sinfo_stream == 0) {
        fprintf(files[0], "%s", buffer);
        count0++;
        memset(buffer, 0, sizeof(buffer));
        continue;
    }

    if(sndrcvinfo.sinfo_stream == 1) {
        fprintf(files[1], "%s", buffer);
        count1++;
        memset(buffer, 0, sizeof(buffer));
        continue;
    }

    if(sndrcvinfo.sinfo_stream == 2) {
        fprintf(files[2], "%s", buffer);
        count2++;
        memset(buffer, 0, sizeof(buffer));
        continue;
    }

}

gettimeofday(&end, NULL);

close(sockCli);

for(i=0; i<3; i++)
    fclose(files[i]);

sec = end.tv_sec - begin.tv_sec;

if (end.tv_usec > begin.tv_usec)
    usecs = end.tv_usec - begin.tv_usec;
else
    usecs = begin.tv_usec - end.tv_sec;

printf("Time elapsed is %d,%d\n", sec, usecs);
printf("Received\n%d messages on stream 0\n%d messages on stream 1\n%d messages on stream 2\n", count0, count1, count2);
return 0;



}

也许我们正在以一种糟糕的方式使用 stcp_() API 或其他一些错误。这似乎是我们唯一正确的方法,因为我们读到多流服务器应该是一个迭代服务器,这就是我们所做的。有一种特殊的额外类型的套接字,称为 SOCK_SEQPACKET 用于一对多样式,但我们不清楚如何使用它,因为没有示例。这可能是关键吗?那么,您能否就如何实现一个好的多流 SCTP 应用程序给我们一些建议?

4

0 回答 0