0

私は現在、BSD ライクなソケット API を使用して開発しています。前に別の関連する質問をしました: lwip stack netconn api keep connection "keep-alive"

現在、次の構造を使用しています。

接続が確立された場合に新しいスレッドを開く 1 つのリッスン スレッド:

portTASK_FUNCTION( vModbusServer, pvParameters ) {
int lSocket;
struct sockaddr_in sLocalAddr;

lSocket = lwip_socket(AF_INET, SOCK_STREAM, 0);

if (lSocket < 0) return; // check error

memset((char *)&sLocalAddr, 0, sizeof(sLocalAddr));
sLocalAddr.sin_family = AF_INET;
sLocalAddr.sin_len = sizeof(sLocalAddr);
sLocalAddr.sin_addr.s_addr = htonl(INADDR_ANY);
sLocalAddr.sin_port = MODBUS_PORT;

if (lwip_bind(lSocket, (struct sockaddr *)&sLocalAddr, sizeof(sLocalAddr)) < 0) {
    lwip_close(lSocket);
    return;
}

if ( lwip_listen(lSocket, 20) != 0 ) {
    lwip_close(lSocket);
    return;
}

while (1) {
    vTaskDelay(1);
    int clientfd;
    struct sockaddr_in client_addr;
    int addrlen=sizeof(client_addr);

    clientfd = lwip_accept(lSocket, (struct sockaddr*)&client_addr, (socklen_t)&addrlen);
    
    if (clientfd>0) {
        sys_thread_new( "MODBUSResponder", vModbusResponder, ( void * ) &clientfd,
               lwipMODBUS_SERVER_STACK_SIZE,
               lwipMODBUS_SERVER_PRIORITY );
    }
}
lwip_close(lSocket); }

このスレッドが作成されます (応答スレッド):

vModbusResponder( void *pvParameters ) {
char buffer[12];
int nbytes;
int *temp = (int*) pvParameters;
int clientfd = *temp;

do {
    nbytes=lwip_recv(clientfd, buffer, sizeof(buffer),0);
    if (nbytes>0) { //no error

    }
}  while (nbytes>0);
lwip_close(clientfd);
vTaskDelete(NULL); }

これは、組み込みデバイスに接続する 2 台の PC など、2 つの接続 (2 つの応答スレッド) に最適ですが、3 台目の PC に接続しようとすると、最初の接続が切断されます。なぜそれが起こるのかわかりません。接続は、RST を使用して組み込みデバイス (lwip) から切断されます。4 台目の PC を接続すると、2 台目の接続が切断されます。

私は次のことを試しました:

この行を次のように編集します。

SYS_THREAD_MAX 30 を定義します

誰かがいくつかのヒントを与えることができますか? 私は何か間違っていますか?

4

1 に答える 1

1

解決策を見つけました: 次の構成を編集しませんでした:

#define MEMP_NUM_TCP_PCB        2 // I edited this to 5
#define MEMP_NUM_NETBUF         3 // I edited this to 5
#define MEMP_NUM_NETCONN        4 // I edited this to 5

これで、同時に 5 つの TCP 接続をセットアップできます。6 番目の接続を開こうとすると、RST が送信されます。

@ジョエル・カニンガム:

「しかし、clientfd を渡す方法は安全ではありません。フォークされたスレッドが実行され、実行が元のスレッドに戻る前に pvParameter を参照するという保証はありません (次のスレッドで clientfd が再割り当てされます)。 call to accept())" RTOS が TCP 接続を開く前にリッスンしているソケットに戻ることはありますか? これを防ぐ最善の方法は何ですか?リッスンしているソケットよりも高い優先順位を付けますか?

于 2015-05-15T19:28:24.947 に答える