1

SCTP で簡単なクライアント サーバー アプリケーションを作成しました。クライアントはサーバーに接続して 3 つのストリームを開き、サーバーはストリームごとにファイルを送信します。問題は、3 つのストリームを制御する方法がわからないことです。ストリーム i 0 からの sctp_rcvmsg() のタイミングを知るには、そのストリームのファイル転送が終了したことを意味します...しかし、sctp_recvmsg() は決して停止します。これが私のコードです。クライアント

#include <sys/types.h>
#include <sys/socket.h>
#include <signal.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 <net/if.h>
#include <stdlib.h>
#include <time.h>

#define BUFFERSIZE 1024

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

int i, sockCliSCTP, flags, res;

/* Server netwrok informations */
struct sockaddr_in servAddr;

/* To get which stream it has received data from */
struct sctp_sndrcvinfo sndrcvinfo;

/* Init message to setup number of streams */
struct sctp_initmsg initmsg;

/* Catching events */
struct sctp_event_subscribe events;

/* Buffer to receive files */
char buffer[BUFFERSIZE];

/* Remove previous recently used files */
remove("first.txt");
remove("second.txt");
remove("third.txt");

char ipServ[32] = "127.0.0.1";
short int servPort = 29008;

/* BEGIN SCTP PART */
/* Creating client socket for SCTP protocol */
sockCliSCTP = socket( AF_INET, SOCK_STREAM, IPPROTO_SCTP );

/* Specify that a maximum of 3 streams will be available per socket */
memset( &initmsg, 0, sizeof(initmsg) );
initmsg.sinit_num_ostreams = 3; /* output streams */
initmsg.sinit_max_instreams = 3; /* input streams */
initmsg.sinit_max_attempts = 2;
setsockopt(sockCliSCTP, IPPROTO_SCTP, SCTP_INITMSG, &initmsg, sizeof(initmsg) );

/* Initializing server network data structs */
bzero( (void *)&servAddr, sizeof(servAddr) );
servAddr.sin_family = AF_INET;
inet_pton(AF_INET, ipServ, &servAddr.sin_addr);
servAddr.sin_port = htons(29008);
int sizeServ = sizeof(servAddr);

/* Connect to server */
res = connect(sockCliSCTP, (struct sockaddr *)&servAddr, sizeof(servAddr));
if (res < 0) {
    printf("Connection to server refused!\n");
    exit(1);
}

memset( (void *)&events, 0, sizeof(events) );
events.sctp_data_io_event = 1;
res = setsockopt(sockCliSCTP, SOL_SCTP, SCTP_EVENTS, (const void *)&events, sizeof(events));
if (res < 0) {
    printf("setsockopt failed!\n");
    exit(1);
}

/* The clients simply waits and receives for three files from the server.
 * The size of the files is increased each time this client is launched. */

FILE *oneF, *twoF, *threeF;
oneF = fopen("first.txt", "a"); /* Stream 0 */
twoF = fopen("second.txt", "a"); /* Stream 1 */
threeF = fopen("third.txt", "a"); /* Stream 2 */

/* To measure time */
time_t timeStart;
time_t timeEnd;
time_t timeRes = 0;

time(&timeStart);

int count0 = 0, count1 = 0, count2 = 0;

int checkRead[3];
for(i = 0; i<3; i++) {
    checkRead[i] = 1;
}


/* Receiving in parallel the files from 3 streams */
while(checkRead[0] || checkRead[1] || checkRead[2]) {

    printf("%d %d %d\n", checkRead[0], checkRead[1], checkRead[2]);

    res = sctp_recvmsg(sockCliSCTP, (void*)buffer, sizeof(buffer), (struct sockaddr*)&servAddr, (socklen_t *)&sizeServ, &sndrcvinfo, &flags);

    if (res == 0) {
        printf("%d stream is zero\n", sndrcvinfo.sinfo_stream);
        checkRead[sndrcvinfo.sinfo_stream] = 0;
        continue;
    }


    /* Check from which stream the data came in */
    switch(sndrcvinfo.sinfo_stream) {

    /* Write on file oneF --> first.txt */
    case 0:
        count0++;
        printf("Message received from stream 0\n");
        //printf("%s\n\n", buffer);
        fprintf(oneF, "%s", buffer);
        break;



    /* Write on file twoF --> second.txt */
    case 1:
        count1++;
        printf("Message received from stream 1\n");
        //printf("%s\n\n", buffer);
        fprintf(twoF, "%s", buffer);
        break;




    /* Write on file threeF --> third.txt */
    case 2:
        count2++;
        printf("Message received from stream 2\n");
        //printf("%s\n\n", buffer);
        fprintf(threeF, "%s", buffer);
        break;


    }

    memset(buffer, 0, sizeof(buffer));
    sleep(1);
}

close(sockCliSCTP);

time(&timeEnd);
timeRes = timeEnd - timeStart;
printf("Time elapsed is: %d seconds\n", (int)timeRes);

printf("%d messages on stream 0,\n %d messages on stream 1,\n %d messages on stream 2\n", count0, count1, count2);


}

そしてサーバー:

#include <sys/types.h>
#include <sys/socket.h>
#include <signal.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 <net/if.h>
#include <stdlib.h>
#include <time.h>
#include <sys/stat.h>
#include <fcntl.h>

#define BUFFERSIZE 1024

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

int sockCli, sockServ, one, two, three, i, res;

struct sockaddr_in client, server;

/* data struct to declarate streams */
struct sctp_initmsg initmsg;

/* buffer to read from file */
char buffer[BUFFERSIZE];

/* socket server listening */
sockServ = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP);

bzero( (void *)&client, sizeof(client));
bzero( (void *)&server, sizeof(server));


/* Preparing sever data struct and bind() */
bzero( (void *)&server, sizeof(server) );
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl( INADDR_ANY );
server.sin_port = htons(29008);

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

/* Maximum of 3 streams will be available per socket */
memset( &initmsg, 0, sizeof(initmsg) );
initmsg.sinit_num_ostreams = 3;
initmsg.sinit_max_instreams = 3;
initmsg.sinit_max_attempts = 2;

res = setsockopt(sockServ, IPPROTO_SCTP, SCTP_INITMSG, &initmsg, sizeof(initmsg));
if (res < 0) {
    printf("setsockopt() failed!\n");
    exit(1);
}


/* Preparing the three files to be sent */
one = open("files/first.txt", O_RDONLY);
if (one < 0) {
    printf("Error on opening first file!\n");
    exit(1);
}

two = open("files/second.txt", O_RDONLY);
if (two < 0) {
    printf("Error on opening second file!\n");
    exit(1);
}

three = open("files/third.txt", O_RDONLY);
if (three < 0) {
    printf("Error on opening third files!\n");
    exit(1);
}


int checkFiles[3];
for(i=0; i<3; i++) {
    checkFiles[i] = 1;
}


res = listen(sockServ, 5);
if (res < 0) {
    printf("listen() failed!\n");
    exit(1);
}



while(1) {

    ssize_t readRes;
    int len = sizeof(client);
    sockCli = accept(sockServ, (struct sockaddr*)&client, &len);

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

    printf("Associated to client!\n");

    while(1) {

        memset(buffer, 0, sizeof(buffer));
        if ((readRes = read(one, (void*)buffer, sizeof(buffer))) > 0) {
            sctp_sendmsg(sockCli, (void*)buffer, (size_t)strlen(buffer), NULL, 0, 0, 0, 0 /* stream number */, 0, 0);
        }


        memset(buffer, 0, sizeof(buffer));
        if ((readRes = read(two, (void*)buffer, sizeof(buffer))) > 0) {
            sctp_sendmsg(sockCli, (void*)buffer, (size_t)strlen(buffer), NULL, 0, 0, 0, 1 /* stream number */, 0, 0);
        }


        memset(buffer, 0, sizeof(buffer));
        if ((readRes = read(three, (void*)buffer, sizeof(buffer))) > 0) {
            sctp_sendmsg(sockCli, (void*)buffer, (size_t)strlen(buffer), NULL, 0, 0, 0, 2 /* stream number */, 0, 0);
        }

        else {break;}

    }

    close(sockCli);
    close(one);
    close(two);
    close(three);




}



}

どこで間違いを犯していますか?:(

4

1 に答える 1

2

sctp_recvmsgは、単一のストリームからメッセージを受信しません。受信したすべてのメッセージを返すだけで、アプリケーションはメッセージがどのストリームから来たのかを判断できます。

このコードが実行されると、すべてのデータがクライアントによって受信された後:

res = sctp_recvmsg(sockCliSCTP, (void*)buffer, sizeof(buffer), (struct sockaddr*)&servAddr, (socklen_t *)&sizeServ, &sndrcvinfo, &flags);

if (res == 0) {
    printf("%d stream is zero\n", sndrcvinfo.sinfo_stream);
    checkRead[sndrcvinfo.sinfo_stream] = 0;
    continue;
}

メッセージが受信されず、sndrcvinfo構造体が変更されないため、 resは 0 になります。そのため、 sndrcvinfo.sinfo_streamは、最後のメッセージが送信されたストリームと同じままになり、checkRead[]値を変更しないため、ループに陥ります。

サーバー/クライアントの動作がおかしくなる他のエラーがいくつかあります。

たとえば、サーバーがファイル記述子を閉じ、2 回目はデータを送信しないため、セグメンテーション違反なしでクライアントを 2 回続けて実行することはできません。このため、次の場合にセグメンテーション違反が発生します。

 checkRead[sndrcvinfo.sinfo_stream] = 0;

sndrcvinfoは null ポインターになるためです。

于 2013-03-22T20:00:46.853 に答える