setsockopt(SO_REUSEADDR) はどのように使用すればいいですか? 質問する

setsockopt(SO_REUSEADDR) はどのように使用すればいいですか? 質問する

私は、Raspberry Pi で独自の http サーバーを実行しています。問題は、プログラムを停止して再起動すると、ポートが使用できなくなることです。大量のリクエストを受信すると、同じ問題が発生することがあります。
エラーが発生してもポートを使い続けられるように SO_REUSEADDR を使用したいのですが、うまくセットアップできませんでした。以下は私のコードです。
表示されるエラーは、「バインディングでエラーが発生しました: アドレスが既に使用されています」です。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>

void error(const char *msg)
{
    perror(msg);
    exit(1);
}

int main(int argc, char *argv[])
{
    printf("Starting Listener\n");
     int sockfd, newsockfd, portno;
     socklen_t clilen;
     char buffer[256];
     struct sockaddr_in serv_addr, cli_addr;
     int n;
     if (argc < 2) {
         fprintf(stderr,"ERROR, no port provided\n");
         exit(1);
     }
     sockfd = socket(AF_INET, SOCK_STREAM, 0);
     if (sockfd < 0) 
        error("ERROR opening socket");
     bzero((char *) &serv_addr, sizeof(serv_addr));
     portno = atoi(argv[1]);
     serv_addr.sin_family = AF_INET;
     serv_addr.sin_addr.s_addr = INADDR_ANY;
     serv_addr.sin_port = htons(portno);
     if (bind(sockfd, (struct sockaddr *) &serv_addr,
              sizeof(serv_addr)) < 0) 
              error("ERROR on binding");

     printf("about to listen\n");
     listen(sockfd,5);
     printf("finished listening\n");
     clilen = sizeof(cli_addr);
     printf("About to accept\n");

     int i;
     for(i=0; i<100; i++){
         newsockfd = accept(sockfd, 
                 (struct sockaddr *) &cli_addr, 
                 &clilen);

         if (newsockfd < 0) 
             error("ERROR on accept");
         bzero(buffer,256);
         n = read(newsockfd,buffer,255);
         if (n < 0) error("ERROR reading from socket");
         printf("Here is the message: %s\n",buffer);
         n = write(newsockfd,"I got your message",18);
         if (n < 0) error("ERROR writing to socket");
         close(newsockfd);
     }
     close(sockfd);
     return 0; 
}

ベストアンサー1

ソケットが正常に初期化された後にオプションを設定します。つまり、次のようになります。

sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) 
    error("ERROR opening socket");

(標準で)追加することができますC99 複合リテラルサポート):

if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) < 0)
    error("setsockopt(SO_REUSEADDR) failed");

または:

const int enable = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0)
    error("setsockopt(SO_REUSEADDR) failed");

に加えてSO_REUSEADDR、目的の動作を得るには を設定する必要があることに注意してくださいSO_REUSEPORT。これは、両方のオプションでまったく同じ方法で実行されます。

おすすめ記事