首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在c中读取来自套接字的回复?

如何在c中读取来自套接字的回复?
EN

Stack Overflow用户
提问于 2010-09-17 18:28:59
回答 3查看 466关注 0票数 1

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

代码语言:javascript
复制
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.

对于第三种情况,我有一段困难的时间。我没有收到来自the服务器的任何响应。

下面是我的代码:

代码语言:javascript
复制
    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);
   }
 }
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-09-17 18:53:13

HTTP请求以两个回车换行符("\r\n\r\n")序列终止。您构造请求的方式甚至不能确保它有一个请求。也许就像这样:

代码语言:javascript
复制
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
EN

Stack Overflow用户

发布于 2010-09-17 18:46:17

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

票数 0
EN

Stack Overflow用户

发布于 2010-09-17 19:23:32

这段代码中有几个开放的循环漏洞,可能会导致这个问题。我真的把赌注押在第二点上。

1- connectTCP真的有效吗?它是否真的返回了一个工作的TCP套接字。你可以很容易地关闭它,在调用write()时检查错误,而不是将它们强制转换为空。

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

3- double \r\n不是必需的,一个'\n‘(unix约定)就足够了。

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

5-注意在缓冲区中的位置n写入。如果读缓冲区已满,则可能超出缓冲区末尾一位。

5-如果你想要的不仅仅是发送一个命令并得到答案,你必须编写更复杂的代码来同时管理write()和read()。正如另一位发帖者建议的那样,select可能是一个好主意(可能比线程更简单)。您也可以在命令发送和接收之间阻止更多的交替,但所有这些都可能是为了解决其他问题。

下面是得到答案的一段工作代码(与gcc一起在Linux上测试)。和你最初的那个没有太大的不同,希望它能帮助你弥补漏洞。

代码语言:javascript
复制
#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 );
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3734536

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档