如何在c中读取socket的回复?

时间:2010-09-17 10:28:59

标签: c sockets webserver recv

我正在尝试编写一个执行以下操作的TCP客户端:

1. Establish TCP connection to webserver
2. Accept GET request command from user's console
3. Client should get a reply back from webserver after each GET request.

我在第三个条件下遇到困难。我没有从网络服务器收到任何回复。

这是我的代码:

    s = connectTCP(host, service);
 while (fgets(buf, sizeof(buf), stdin)) {
   buf[LINELEN-2]='\r';    /* ensure catridge return   */
   buf[LINELEN-1]='\n'; /* ensure line feed return  */
   buf[LINELEN] = '\0'; /* ensure line null-terminated */
   outchars = strlen(buf);
   (void) write(s, buf, outchars);
   printf("Start reading from socket...\n");
   fflush(stdout);
   while( (n = read(s, buf, LINELEN)) > 0) {
    buf[n] = '\0';  /* ensure null-terminated */
    (void) fputs( buf, stdout );
    fflush(stdout);
   }
 }

3 个答案:

答案 0 :(得分:1)

HTTP请求以 two carriage-return-linefeed(“\ r \ n \ n \ n \ n \ n”)序列终止。您构建请求的方式甚至不能确保它有一个。也许更像是:

while (fgets(buf, sizeof(buf) - 3, stdin)) {
    size_t outsz = strlen(buf);
    if (outsz > 0 && buf[outsz - 1] == '\n')
        outsz--;
    strcpy(buf + outsz, "\r\n\r\n");
    write(s, buf, outsz + 4);

答案 1 :(得分:0)

您使用的是哪些套接字?如果您使用(windows)berkley套接字,则可以使用select来测试数据,使用recv / recvfrom来获取数据

答案 2 :(得分:0)

此代码中有几个开环孔可能导致问题。我真的打赌第2点。

1- connectTCP真的有效吗?它确实返回了一个工作的TCP套接字。在调用write()而不是将它们转换为void时,您可以轻松关闭那个检查错误。

2-如果LINELEN是一个类似于数组大小的常量,如果用户输入和数组末尾之间存在垃圾,那么将\r\n放在数组的末尾将没有多大帮助(机会)可能有一些0)。 sizeof(buf)是最大合法值,不一定是用户输入内容的大小。

不需要3-双\r\n,一个'\ n'(unix约定)就足够了。

4 - 使用交互式用户输入进行测试通常不是一个好主意,它使代码更难以调试和测试。

5 - 如果读取缓冲区已满,请注意在缓冲区中的位置n写入,它可能是缓冲区末尾的一个。

5 - 如果你想要的不只是发送一个命令并获得答案,你将不得不编写更精细的代码来管理write()和read()。正如另一张海报建议选择可能是一个好主意(可能比线程简单)。你也可以阻止更多的命令发送和接收,但所有这些可能是其他问题。

下面是一段代码(在Linux上用gcc测试),可以得到答案。从最初的那个开始,并没有那么不同,希望它能帮助你弥补漏洞。

#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/un.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

enum {
    LINELEN = 1024
};

int main(){
    char buf[LINELEN];
    int n = 0;
    unsigned int option_len;
    int allow_reuse = 1;
    int sck = socket(PF_INET, SOCK_STREAM, 0);
    char * ip = "www.google.com";
    char * command = "GET http://www.google.com\n";

    /* connect to socket */
    struct sockaddr_in s;
    memset(&s, 0, sizeof(struct sockaddr_in));
    s.sin_family = AF_INET;
    s.sin_port = htons(80);
    s.sin_addr.s_addr = inet_addr(ip);
    if (s.sin_addr.s_addr == INADDR_NONE) {
        struct hostent *h = gethostbyname(ip);
        if (!h) {
            printf("DNS resolution failed for %s\n", ip);
            exit(0);
        }
        s.sin_addr.s_addr = *((int*)(*(h->h_addr_list)));
    }
    connect(sck, (struct sockaddr*)&s, sizeof(s));

    /* write command */
    printf("Write to socket...\n");
    write(sck, command, strlen(command));

    /* get answer */
    printf("Start reading from socket...\n");
    while((n = read(sck, buf, LINELEN-1)) > 0) {
       buf[n] = '\0';  /* ensure null-terminated */
       fputs( buf, stdout );
    }
}