首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >回顾互联网连接敲击方法

回顾互联网连接敲击方法
EN

Code Review用户
提问于 2013-08-15 18:47:03
回答 1查看 348关注 0票数 6

这是一些C代码,我必须简单地测试互联网连接。任何关于效率和重构本程序的评论/建议将不胜感激。

代码语言:javascript
复制
int testConnection(void)
{
    int status;
    struct addrinfo host_info;
    struct addrinfo *host_info_list;
    memset(&host_info, 0, sizeof host_info);
    #ifdef DEBUG
    fprintf(stdout,"Setting up the structs...");
    #endif
    host_info.ai_family = AF_UNSPEC;     // IP version not specified. Can be both.
    host_info.ai_socktype = SOCK_STREAM; // Use SOCK_STREAM for TCP or SOCK_DGRAM for UDP.

    status = getaddrinfo("www.google.com", "80", &host_info, &host_info_list);
    if (status != 0)  fprintf(stdout, "Address info error:: %s\n", gai_strerror(status));

    #ifdef DEBUG
    fprintf(stdout, "Creating a socket...\n");
    #endif
    int socketfd ;
    socketfd = socket(host_info_list->ai_family, host_info_list->ai_socktype, host_info_list->ai_protocol);
    if (socketfd == -1)  fprintf(stderr, "Socket error\n");

    #ifdef DEBUG
    fprintf(stdout, "Connecting...");
    #endif
    status = connect(socketfd, host_info_list->ai_addr, host_info_list->ai_addrlen);
    if (status < 0) fprintf(stderr, "Error while connecting.\n");

    #ifdef DEBUG
    fprintf(stdout, "Sending message...\n");
    #endif
    const char *msg = "GET / HTTP/1.1\nhost: www.google.com\n\n";
    int len = strlen(msg);
    ssize_t bytes_sent = send(socketfd, msg, len, 0);
    if (bytes_sent == 0) fprintf(stderr, "No bytes sent.\n");
    #ifdef DEBUG
    fprintf(stdout, "Bytes sent: %d\n", bytes_sent);
    fprintf(stdout, "Waiting to recieve data...\n");
    #endif
    char incomming_data_buffer[1000];
    ssize_t bytes_recieved = recv(socketfd, incomming_data_buffer,1000, 0);
    // If no data arrives, the program will just wait here until some data arrives.
    if (bytes_recieved == 0) fprintf(stderr, "Host shut down.\n");
    if (bytes_recieved == -1) fprintf(stderr, "Recieve error.\n");
    incomming_data_buffer[bytes_recieved - 2] = '\0';
    #ifdef DEBUG
    fprintf(stdout, "Bytes recieved: %d\n", bytes_recieved);
    fprintf(stdout, "%s\n", incomming_data_buffer);
    fprintf(stdout, "Receiving complete. Closing socket...\n");
    #endif
    freeaddrinfo(host_info_list);
    close(socketfd);
    #ifdef DEBUG
    fprintf(stdout, "Socket closed.\n");
    #endif
    return 0;
}
EN

回答 1

Code Review用户

回答已采纳

发布于 2013-08-15 20:16:26

一些评论,大多是次要的评论:

我将提取到一个函数的服务器连接:

代码语言:javascript
复制
static int connect_server(const struct addrinfo *host_info)
{
    struct addrinfo *host_info_list;
    int fd = -1;
    int status = getaddrinfo(...);
    while(...) {
        fd = socket(...);
        status = connect(...);
    }
    freeaddrinfo(host_info_list);
    return fd;
}

所有那些调试的东西都让人分心。也许这是暂时的,但如果你想把它留在里面,我建议提取它:

代码语言:javascript
复制
#include <stdarg.h>

static inline void debug(const char *format, ...)
{
#ifdef DEBUG
    va_list ap;
    va_start(ap, format);
    vfprintf(stdout, format, ap);
    va_end(ap);
#endif
}

并称之为:

代码语言:javascript
复制
debug("Bytes recieved: %ld\n%s\nReceiving complete. Closing socket...\n",
      bytes_recieved,
      incomming_data_buffer);

如果调试未定义,内联debug函数将为空,并将在编译期间被排除-它将消失。

显然你需要循环才能读到整个信息..。读完后,你会扔掉最后两个字节。

代码语言:javascript
复制
buffer[bytes_recieved - 2] = '\0';

recv调用填充了缓冲区,因此要正确终止\0,需要指定一个较小的缓冲区:

代码语言:javascript
复制
char buffer[1000];
ssize_t bytes_recieved = recv(socketfd, buffer, sizeof buffer - 1, 0);
...
if (bytes_recieved > 0) {
    buffer[bytes_recieved] = '\0';
}

注意sizeof的使用而不是显式的1000

还有其他的事情..。

  • getaddrinfo的手册页建议循环遍历返回的地址列表,而不是仅仅使用第一个地址(以防第一个地址不起作用)。
  • 当某件事失败时,你应该退出而不是继续。
  • 不要对常量字符串使用strlen,而是使用sizeof:const char msg[] = "GET / HTTP/1.1\nhost: www.google.com\n\n";ssize_t bytes_sent = send(socketfd,msg,sizeof of msg - 1,0);注意msg[],而不是*msg
  • 可能在阅读失败时使用perrorstrerror等。
  • camelCase函数名,但其他地方的separate_word名称。
票数 8
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/29805

复制
相关文章

相似问题

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