c - 我如何使用 setsockopt(SO_REUSEADDR)?

标签 c sockets raspberry-pi

我在树莓派上运行自己的 http 服务器。问题是当我停止程序并重新启动它时,该端口不再可用。有时我在收到大量请求时会遇到同样的问题。
我想使用 SO_REUSEADDR 这样即使发生错误我也可以继续使用该端口但没有运气设置它。下面是我的代码。
我得到的错误是“绑定(bind)错误:地址已在使用中”。

#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; 
}

最佳答案

在成功初始化套接字后设置选项。所以,之后:

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

您可以添加(使用标准 C99 compound literal 支持):

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 以获得所需的行为。这两个选项的完成方式完全相同。

关于c - 我如何使用 setsockopt(SO_REUSEADDR)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24194961/

相关文章:

c - SysGCC 工具链在 sysroot 中找不到文件

创建多个消息队列,并使用队列的唯一键

c - 冒泡排序算法实现(Haskell vs. C)

raspberry-pi - 未收到 Android Things GpioCallback

docker - 如何在只读主机文件系统上运行 docker daemon

c - 原始套接字编程 - 为什么 printf() 会影响数据包发送?

c - 递归循环

c - 如何计算一排 N 个盒子的 Rect 填充长度 L,它们之间有 S 个空间

c - 通过套接字发送图像

java - 优化使用 inputstreamreader 的 java 多线程服务器