2016-08-05 37 views
0

我有一个HTTP资源,其大小为3GB。urllib2.urlopen(URL).read()在虚拟机操作系统超时X 10.11(VMware工作站12 PRO)

我有一些像下面的代码。

#the url is actually a http resource which is 3GB. 
res = urllib2.urlopen(url, timeout = 10) 
data = res.read(1024) 
while data: 
    data = res.read(1024) 

在VMware工作站11或以下,它的工作原理fine.But在VMware工作站12,它给我的错误。

Traceback (most recent call last): 
    File "<stdin>", line 2, in <module> 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 384, in read 
    data = self._sock.recv(left) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 612, in read 
    s = self.fp.read(amt) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 384, in read 
    data = self._sock.recv(left) 
socket.timeout: timed out 

我使用Safari浏览器在Vmware工作站12下载资源,它工作正常。如果资源小于10K等一些大小,它也可以正常工作。

+1

你有没有尝试删除'超时= 10',看看请求的URL是否在默认的超时时间内处理? – Eduard

+0

@EduardDaduya。如果我删除超时,线程将永久卡住。 –

+0

我的歉意,我误解了手边的问题,您正在通过urlopen成功检索数据,但读取检索到的数据引发了上述异常。我还没遇到的东西。我相信这个解释会帮助你解决你目前的问题http://stackoverflow.com/a/26765074/1809168 – Eduard

回答

0

他们固定在VMware Fusion 8.5.7!见https://communities.vmware.com/thread/544049

我真的不能提供你一个答案,现在和我有什么要说的是比注释长了一点,但我遇到了在VMware Fusion中的类似问题临8.5 10.12与Python的urllib2的。它与urllib2无关。

我开始在传输会话随机接受这个问题,一些Wireshark的调试之后,决定了它是由于TCP窗口上的接收器达到0。出于某种原因,它不会再更新。

如果你不知道TCP窗口是什么,它基本上是接收缓冲区的一个TCP连接的一端的大小。该缓冲区应该扩张和收缩是正常传输时的拥塞控制机制,但不应该发生的事情越来越停留在0

您的会话的转移工作,小于10K的原因窗口是因为默认的TCP窗口通常大约8k。任何比这更少的东西都不会填满接收缓冲区。再者,你基本上希望你处理数据的速度比你接收数据的速度快。

要在我的本地机器上重现此问题,请使用cc client.c -o clientcc server.c -o server编译的两个[特别]编写的C程序。运行虚拟机中的客户端和本地计算机上的服务器。

server.c:

/* server.c */ 
/* A simple server in the internet domain using TCP 
    The port number is passed as an argument */ 
#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[]) 
{ 
    int sockfd, newsockfd, portno; 
    socklen_t clilen; 
    char buffer[1024]; 
    struct sockaddr_in serv_addr, cli_addr; 
    int n, total; 
    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"); 
    listen(sockfd,5); 
    clilen = sizeof(cli_addr); 
    newsockfd = accept(sockfd, 
       (struct sockaddr *) &cli_addr, 
       &clilen); 
    if (newsockfd < 0) 
     error("ERROR on accept"); 
    memset(buffer, '0xAB', sizeof(buffer)); 
    total = 0; 
    for (;;) { 
     n = write(newsockfd, buffer, sizeof(buffer)); 
     if (n < 0) 
      error("ERROR writing to socket"); 
     else 
      total += n; 
      printf("wrote %d/%d\n", n, total); 
    } 
    close(newsockfd); 
    close(sockfd); 
    return 0; 
} 

client.c:

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

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

int main(int argc, char *argv[]) 
{ 
    fd_set set; 
    int sockfd, portno, n, total, rv; 
    struct sockaddr_in serv_addr; 
    struct hostent *server; 
    struct timeval timeout; 

    char buffer[256]; 
    if (argc < 3) { 
     fprintf(stderr,"usage %s hostname port\n", argv[0]); 
     exit(0); 
    } 
    portno = atoi(argv[2]); 
    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (sockfd < 0) 
     error("ERROR opening socket"); 
    server = gethostbyname(argv[1]); 
    if (server == NULL) { 
     fprintf(stderr,"ERROR, no such host\n"); 
     exit(0); 
    } 
    bzero((char *) &serv_addr, sizeof(serv_addr)); 
    serv_addr.sin_family = AF_INET; 
    bcopy((char *)server->h_addr, 
     (char *)&serv_addr.sin_addr.s_addr, 
     server->h_length); 
    serv_addr.sin_port = htons(portno); 
    if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) 
     error("ERROR connecting"); 
    bzero(buffer, 256); 

    FD_ZERO(&set); 
    FD_SET(sockfd, &set); 

    sleep(1); 

    timeout.tv_sec = 1; 
    timeout.tv_usec = 0; 
    total = 0; 
    for (;;) { 
     rv = select(sockfd + 1, &set, NULL, NULL, &timeout); 
     if (rv == -1) { 
      perror("select\n"); 
     } else if(rv == 0) { 
      printf("timeout\n"); 
      break; 
     } else { 
      n = read(sockfd, buffer, 256); 
      if (n < 0) 
      error("ERROR reading from socket"); 
      total += n; 
      printf("read %d/%d\n", n, total); 
     } 
    } 
    close(sockfd); 
    return 0; 
} 

这些程序都是直接取自http://www.linuxhowtos.org/C_C++/socket.htm与修改报告更多统计和强制执行停顿了。

这里是Wireshark的演示TCP窗口减少到0和粘贴截图:

TCP Zero Window in Wireshark

我目前的理论是,有在对VMware的侧网络堆栈某种错误的客户,但很难说。到目前为止,我尝试过使用三种不同的虚拟网络接口(e1000,e1000e,vlance),并且每个接口都有相同的问题。

我将尝试尝试各种vmx选项以减少问题发生的可能性,但这显然是稳定系统的杀手,我的用例(虚拟化Jenkins奴隶for CI)根本不允许这种错误。

如果我能学到新东西,我会报告回来。

编辑:我张贴的错误在VMware社区板:再次https://communities.vmware.com/message/2648727

编辑:他们固定在VMware Fusion 8.5.7!请参阅上述链接。

相关问题