Linux C Socket:recv 调用被阻止

2023-12-06

在我的应用程序中,我为一个简单的http服务器创建了一个线程,然后在我的应用程序中我尝试连接到http服务器,但控制在recv调用上被阻止/挂起。

但是,如果尝试使用 linux GET 命令连接到我的应用程序的 http 服务器,我将成功连接到 http 服务器。

根据我的理解,通过搜索谷歌我发现这不是正确的方法。

但如果我想这样做,我应该在什么中创建套接字,以便我可以从应用程序内连接我的 http 服务器。

下面是我的 http 服务器套接字的创建方式

pthread_create(&pt_server, NULL, http_srvr, NULL);

//http server handler
void *http_server()
{
    int sockfd, new_fd;             
    struct sockaddr_in my_addr;     
    struct sockaddr_in their_addr;  
    socklen_t sin_size;
    struct sigaction sa;
    int yes=1;

    if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
    {
    perror("socket");
    exit(1);
    }

    if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1)
    {
    perror("setsockopt");
    exit(1);
    }

    my_addr.sin_family = AF_INET;               // host byte order
    my_addr.sin_port = htons(HTTP_PORT);        // short, network byte order
    my_addr.sin_addr.s_addr = INADDR_ANY;       // automatically fill with my IP
    memset(&(my_addr.sin_zero), '\0', 8);       // zero the rest of the struct

    if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr))== -1)
    {
    perror("bind");
    exit(1);
    }

    printf("Listening to sockets\n");
    if (listen(sockfd, BACKLOG) == -1)
    {
    perror("listen");
    exit(1);
    }

    sa.sa_handler = sigchld_handler; // reap all dead processes
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_RESTART;
    if (sigaction(SIGCHLD, &sa, NULL) == -1)
    {
    perror("sigaction");
    exit(1);
    }

    printf("server: waiting for connections...\n");

    while(1) {  // main accept() loop
        sin_size = sizeof(struct sockaddr_in);
        if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr,&sin_size)) == -1)
        {
          perror("accept");
          continue;
        }
        printf("server: got connection from %s\n",inet_ntoa(their_addr.sin_addr));

        handle_connection(new_fd);
    }
}

以下是我如何对我的 http 服务器进行 http POST

  /* create socket */
  if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    return ERRSOCK;
  setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, 0, 0);


  /* connect to server */
  if (connect(s, &server, sizeof(server)) < 0) 
    ret=ERRCONN;
  else {
    if (pfd) *pfd=s;

    /* create header */
    if (proxy) {
      sprintf(header,
"%s http://%.128s:%d/%.256s HTTP/1.0\015\012User-Agent: %s\015\012%s\015\012",
          command,
          http_server1,
          http_port,
          url,
          http_user_agent,
          additional_header
          );
    } else {
      sprintf(header,
"%s /%.256s HTTP/1.0\015\012User-Agent: %s\015\012%s\015\012",
          command,
          url,
          http_user_agent,
          additional_header
          );
    }

    hlg=strlen(header);


    /* send header */   
    if (send(s,header,hlg,0)!=hlg)
      ret= ERRWRHD;

    /* send data */
    else if (length && data && (send(s,data,length,0)!=length) )
      ret= ERRWRDT;

    else {
      /* read result & check */
      ret=http_read_line(s,header,MAXBUF-1);

下面是http_read_line的内容,并且在这个函数中recv调用被阻塞

static int http_read_line (fd,buffer,max) 
     int fd; /* file descriptor to read from */
     char *buffer; /* placeholder for data */
     int max; /* max number of bytes to read */
{ /* not efficient on long lines (multiple unbuffered 1 char reads) */
  int n=0;
  while (n<max) {
    if (recv(fd,buffer,1,0)!=1) {
      n= -n;
      break;
    }
    n++;
    if (*buffer=='\015') continue; /* ignore CR */
    if (*buffer=='\012') break;    /* LF is the separator */
    buffer++;
  }
  *buffer=0;
  return n;
}

您需要发送 HTTP 1.0 标头,或者阅读 HTTP 1.1 中的内容长度。当服务器没有义务关闭连接时,您正在将流读取到 EOS,因此您会阻塞。 Content-Length 标头告诉您主体中有多少数据:您应该只尝试读取那么多字节。

如果您指定 HTTP 1.0(并且没有花哨的标头),服务器将在发送响应后关闭连接。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux C Socket:recv 调用被阻止 的相关文章

  • Mono 和 WebRequest 速度 - 测试

    在 mono 4 6 2 linux 中 我注意到 wget 下载文件的速度与webclient DownloadString 所以我做了一个小测试来调查 为什么 wget 明显比 C 快 根据我自己的实验 使用 wget 下载 手动读取文
  • 是否可以找到哪个用户位于 localhost TCP 连接的另一端?

    这是一个编程问题 但它是 Linux Unix 特定的 如果我从本地主机获得 TCP 连接 是否有一种简单的方法可以告诉哪个用户在 C 程序内建立了连接而无需 shell 我知道这对于 Unix 域套接字来说并不太难 我已经知道远程 IP
  • recvfrom() 中的 addrlen 字段有何用途?

    我在程序中使用 recvfrom 从我在 src addr 中指定的服务器获取 DGRAM 数据 但是 我不确定为什么需要初始化并传入addrlen 我读了手册页 但不太明白它的意思 如果src addr不为NULL 并且底层协议提供了源地
  • 在 PCL 中使用 System.Net.Sockets(.Net 4.5 + 电话 8)

    我现有的 Net 库已经适用于 Net 4 5 和 Windows Phone 8 现在我想将其转换为可移植类库 突然我无法使用System Net Sockets不再了 我只检查了 Net 4 5和Windows Phone 8 未选择X
  • Linux TCP服务器:在接受连接之前读取客户端的IP地址

    Related C Winsock API如何在接受连接之前获取连接客户端IP https stackoverflow com questions 716209 c winsock api how to get connecting cli
  • 使用netcat将unix套接字传输到tcp套接字

    我正在尝试使用以下命令将 unix 套接字公开为 tcp 套接字 nc lkv 44444 nc Uv var run docker sock 当我尝试访问时localhost 44444 containers json从浏览器中 它不会加
  • 原生 Linux 应用程序可像 ResHacker 一样编辑 Win32 PE

    我想运行自动修改 dll服务 用户提交特定的 dll 我在服务器上修改它 然后用户可以下载 dll的修改版本 是否有任何本机 Linux 应用程序提供常见的 Win32 PE 修改功能 例如图标 字符串 加速器 对话等 至少提供命令行或脚本
  • Accept() 是线程安全的吗?

    我目前正在用 C 语言为我正在做的课程编写一个简单的网络服务器 我们的一项要求是实现一个线程池来使用 pthread 处理连接 我知道我将如何粗略地执行此操作 在主线程中调用accept并将文件描述符传递给freee线程 但是我的朋友建议了
  • Linux 中 AF_UNIX 数据报消息的最大大小是多少?

    目前我已达到 130688 字节的硬限制 如果我尝试在一条消息中发送更大的内容 我会收到一条消息ENOBUFS error 我已经检查过net core rmem default net core wmem default net core
  • /proc/PID 文件格式

    我想从中检索一些流程信息 proc目录 我的问题如下 中的文件是否有标准格式 proc PID 例如 有这个proc PID status文件与Name t ProcName在第一行 我可以在其他地方用空格代替这个文件吗 t或者类似的东西
  • 在 Ubuntu 上纯粹通过 bash 脚本安装 mysql 5.7

    我想要一个无需任何手动输入即可安装 MySQL 5 7 实例的 bash 脚本 我正在关注数字海洋教程 https www digitalocean com community tutorials how to install mysql
  • 在中断时获取 current->pid

    我正在Linux调度程序上写一些东西 我需要知道在我的中断到来之前哪个进程正在运行 当前的结构可用吗 如果我在中断处理程序中执行 current gt pid 我是否可以获得我中断的进程的 pid 你可以 current gt pid存在并
  • 如何在两个不同帐户之间设置无密码身份验证

    我们可以在两台机器的两种不同用途之间设置无密码身份验证吗 例如 计算机A有用户A 计算机B有用户B 我们可以设置密码 ssh 以便计算机 A 上的用户 A 使用其用户帐户 A 登录计算机 B 谢谢你 如果我理解你的问题 你能设置一下吗ssh
  • 如何在 Linux x86_64 上模拟 iret

    我正在编写一个基于 Intel VT 的调试器 由于当 NMI Exiting 1 时 iret 指令在 vmx guest 中的性能发生了变化 所以我应该自己处理vmx主机中的NMI 否则 guest会出现nmi可重入错误 我查了英特尔手
  • sqlite 插入需要很长时间

    我正在将不到 200 000 行插入到 sqlite 数据库表中 我只是在终端中通过 sqlite3 使用一个非常简单的 sql 文件 我打赌它已经运行了至少 30 分钟 这是正常现象还是我应该关闭该过程并尝试不同的方法 sqlite中的插
  • 如何在node.js中分离TCP套接字消息

    我正在尝试使用 TCP 套接字 并且对消息如何到达我的应用程序感到困惑 看来他们已经分手了 有人知道我怎样才能最好地将他们重新组合在一起吗 所有消息均以换行符分隔 r n var stream net createConnection po
  • 如何从 Linux 的 shell 中删除所有以 ._ 开头的文件?

    确实如标题所示 我已将许多文件从 Mac 复制到 Raspberry Pi 这导致了许多以前缀开头的多余文件 我想删除以以下开头的文件夹中的每个文件 我该怎么做 尝试类似的方法 cd path to directory rm rf 或者 如
  • 为什么 UDP 服务器中只有一个套接字?

    我正在准备考试 发现了这个问题 典型的 UDP 服务器可以使用单个套接字来实现 解释一下为什么 对于 TCP 驱动的服务器 我发现创建了两个套接字 一个用于所有客户端访问服务器 另一个用于每个客户端的特定 套接字 用于服务器和客户端之间的进
  • Linux命令列出所有可用命令和别名

    是否有一个 Linux 命令可以列出该终端会话的所有可用命令和别名 就好像您输入 a 并按下 Tab 键一样 但针对的是字母表中的每个字母 或者运行 别名 但也返回命令 为什么 我想运行以下命令并查看命令是否可用 ListAllComman
  • 如何在Python中获取套接字的外部IP?

    当我打电话时socket getsockname 在套接字对象上 它返回我的机器的内部 IP 和端口的元组 但是 我想找回我的外部IP 最便宜 最有效的方式是什么 如果没有外部服务器的配合 这是不可能的 因为您和另一台计算机之间可能存在任意

随机推荐