- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在学习小型 http 客户端的开发,特别是 NONBLOCKING tcp 套接字与 http/1.1 客户端的整体复杂性。
下面的小代码似乎可以在 linux 上运行,但不能在我的 mac os x 10.6.8 上运行。调试后它似乎在使用发送函数循环? linux 和 mac os x/freebsd 之间的非阻塞模式有区别吗?
这是我收到的...
在端口 80 上连接到 google.com(173.194.65.147) ... 好获取/HTTP/1.1主机:google.com用户代理:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/534.52.7 (KHTML, like Gecko) Version/5.1.2 Safari/534.52.7
发送失败:套接字未连接
谁能帮我理解这段代码出了什么问题?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
void
setSockNonBlock(int sock)
{
int flags;
flags = fcntl(sock, F_GETFL, 0);
if (flags < 0) {
perror("fcntl(F_GETFL) failed");
exit(EXIT_FAILURE);
}
if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0) {
perror("fcntl(F_SETFL) failed");
exit(EXIT_FAILURE);
}
}
int
getIP(const char *uri, char *hostname, struct in_addr * ip)
{
char *tmp;
tmp = (char *) malloc(strlen(uri) + 1);
strncpy(tmp, uri, strlen(uri) + 1);
char *p, *q;
p = strstr(tmp, "http://");
if (p == NULL) {
p = tmp;
} else {
p = tmp + 7;
}
q = strstr(p, "/");
if (q != NULL) {
*q = '\0';
} else {
q = tmp + strlen(uri);
}
strncpy(hostname, p, q - p + 1);
free(tmp);
struct hostent *host;
if ((host = gethostbyname(hostname)) == NULL) {
fprintf(stderr, "gethostbyname failed, %s\n", hstrerror(h_errno));
exit(EXIT_FAILURE);
}
int i;
for (i = 0; host->h_addr_list[i] != NULL; i++) {
if (host->h_addrtype == AF_INET) {
memcpy(ip, (struct in_addr *) (host->h_addr_list[i]), sizeof(struct in_addr));
return 1;
}
}
return 0;
}
int
main(int argc, char *argv[])
{
if (argc != 2) {
fprintf(stderr, "USAGE: %s uri\n", argv[0]);
exit(EXIT_FAILURE);
}
char *uri;
uri = argv[1];
char *hostname;
hostname = (char *) malloc(strlen(uri) + 1);
struct in_addr ip;
if (!getIP(uri, hostname, &ip)) {
fprintf(stderr, "getIP for %s failed\n", uri);
exit(EXIT_FAILURE);
}
char ip_str[INET_ADDRSTRLEN];
if (!inet_ntop(AF_INET, &ip, ip_str, INET_ADDRSTRLEN)) {
perror("inet_ntop failed");
exit(EXIT_FAILURE);
}
int sock;
if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket failed");
exit(EXIT_FAILURE);
}
setSockNonBlock(sock);
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr = ip;
serv_addr.sin_port = htons(80);
if (connect(sock, (struct sockaddr *) & serv_addr, sizeof(serv_addr)) == -1 && (errno != EINPROGRESS)) {
perror("connect failed");
exit(EXIT_FAILURE);
}
printf("Connect to %s(%s) on port 80 ... ok \n", hostname, ip_str);
char request[1024] = "";
char *get;
get = strstr(uri, hostname);
if (get == NULL) {
get = "/";
} else {
get += strlen(hostname);
if (*get == '\0') {
get = "/";
}
}
sprintf(request, "GET %s HTTP/1.1\r\nHost: %s\r\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/534.52.7 (KHTML, like Gecko) Version/5.1.2 Safari/534.52.7\r\n\r\n", get, hostname);
printf("%s\n", request);
free(hostname);
char *p = request;
int remaining = strlen(request);
ssize_t sent_size;
while (remaining) {
sent_size = send(sock, p, remaining, 0);
if (sent_size == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
continue;
}
if (sent_size <= 0) {
perror("sent failed");
exit(EXIT_FAILURE);
}
remaining -= sent_size;
p += sent_size;
}
char *resp = NULL;
int resp_size = 0;
char buf[1024];
ssize_t recv_size;
char *tmp;
while (1) {
recv_size = recv(sock, buf, sizeof(buf), 0);
if (recv_size == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
continue;
}
if (recv_size <= 0) {
break;
}
tmp = (char *) realloc(resp, resp_size + recv_size + 1);
if (tmp == NULL) {
fprintf(stderr, "Error: realloc failed, not enough memory to save response");
if (resp) {
free(resp);
}
exit(EXIT_FAILURE);
}
resp = tmp;
tmp = resp + resp_size;
memcpy(tmp, buf, recv_size);
resp_size += recv_size;
resp[resp_size] = '\0';
if (strstr(resp, "</html>")) {
break;
}
}
if (resp) {
printf("%s\n", resp);
free(resp);
}
close(sock);
return 0;
}
最佳答案
我怀疑你的问题是你正在做一个非阻塞的 connect() 但立即通过一些代码,这将需要几毫秒来执行,然后尝试在可能尚未连接的套接字上发送。
您可以通过在连接后将 sleep() 插入几秒钟来进行简单测试,看看这是否是真正的原因。但更大的问题是,至少在目前,您没有任何令人信服的理由使用非阻塞套接字,因为您没有使用任何东西,否则无论如何都会被阻塞。例如,您的发送循环除了检查返回码并尝试再次发送外什么都不做。你也可以阻止。也许利用非阻塞的代码是您下一阶段的目标?
无论如何,请查看select()或 poll() (还有像 pselect
、ppoll
等 friend )。这将有助于多路复用。
关于C http O_NONBLOCK 模式问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8465882/
我正在使用套接字并使用 fcntl 设置 O_NONBLOCK,但应用程序仍然占用 100% 的 CPU。即使我正在使用等待时间为 1 毫秒的选择。 出于阅读目的,我正在使用 recv。 我在没有 O
根据我在 The Open Group 网站上阅读的内容 fcntl , open , read , 和 write , 我得到的印象是 O_NONBLOCK 是否设置在文件描述符上,因此非阻塞 I/
情况:在 POSIX 环境中,我使用串行端口库,该库通过设置了 O_NONBLOCK 标志的 open(...) 打开设备。正如 open 调用的手册页所述,open 本身不会因该标志而阻塞。 问题:
我实现了套接字超时并重试,但为了做到这一点,我必须将套接字设置为非阻塞套接字。但是,我需要套接字来阻止。这是我尝试解决这两个问题。这是行不通的。随后的发送调用会阻塞但从不发送任何数据。当我在没有选择和
我正在学习小型 http 客户端的开发,特别是 NONBLOCKING tcp 套接字与 http/1.1 客户端的整体复杂性。 下面的小代码似乎可以在 linux 上运行,但不能在我的 mac os
我正在我的 C 程序中打开一个文件: pcm->dfd = open(fname, O_RDONLY|O_NONBLOCK); 然后在其上调用 select() 和 read()。 但我的问题是,O_
Strace 摘录(请忽略将 xml 发送到 ssh): dup(12) = 13 getsockname(13, {sa_family
我正在尝试编写一个“更干净”的程序来释放在命名管道处被阻塞的潜在编写器(因为没有读取器正在从管道读取)。但是,当没有写入器被阻塞写入管道时,清理器本身不应阻塞。换句话说,“清理器”必须立即返回/终止,
我一直在使用进程间通信用 C++ 为 linux 编写一个小程序。我在尝试以非阻塞方式读取一个进程并写入(阻塞)另一个进程时遇到问题。问题看起来像这样,当父级尝试使用 O_NONBLOCK(或 O_N
我有一个关于 Clozure CL 的问题。当我试图从 quicklisp 快速加载一个包时。它抛出一个错误。用谷歌搜索,但没有找到任何有用的东西。 这是错误信息: (ql:quickload :dr
我必须使用 unix 套接字(没有 O_NONBLOCK)为一个类编写一个聊天客户端-服务器,并在它们上选择异步 I/O。目前,在服务器上,我从客户端读取了1024字节,并直接处理。 例如,在消息的情
我正在从 C 程序写入 SOCK_STREAM正在从 go 程序监听的 Unix 域套接字,使用 net.Listen("unix", sockname) .当我将套接字设置为 O_NONBLOCK使
如果我使用 fcntl(sockfd, F_SETFL, O_NONBLOCK); 使 TCP 套接字描述符成为非阻塞的,这是否会使所有后续套接字 API 都像 read()/listen()/acc
发送到 mq_timedreceive 的 timespec 设置为 20 秒。 20 秒过去后,errno 返回“资源暂时不可用”(EAGAIN)。此外,这会发送一个信号并使进程崩溃。我期望发生的是
我正在为类编写一个发送器/读取器 IPC C 程序,但我无法将 O_NONBLOCK 标志设置为 0,以便我的读取器在尝试读取的缓冲区为空时阻塞。以下是我正在使用的功能: int set_nonblo
当我在阻塞模式下使用套接字时,我可以有一个简单的系统来做这样的事情: client server A -------------------> B register
是否可以实现非阻塞客户端套接字?我试过使用 sockfd = socket(AF_INET, SOCK_STREAM, 0); fcntl(sockfd, F_SETFL, O_NONBLOCK);
我正在使用 select() 和 NONBLOCKING 连接 fd 来接受连接并处理输入和输出。我在处理超过缓冲区大小的大数据传输时遇到一些问题。例如这里: readCount = 1; while
如果我有一个文件描述符,它已使用 open (2) 打开,随后使用 fcntl (2) 设置为 O_NONBLOCK 使用FFI(外部函数接口(interface))。 这意味着几乎每次调用read(
aio_write() 和 O_NONBLOCK write() 有什么区别?此外,我使用 O_NONBLOCK 函数将 write() 用于使用文件描述符的文本文件,并通过在函数前后放置一个计时器来
我是一名优秀的程序员,十分优秀!