首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >低层tcp套接字

低层tcp套接字
EN

Code Review用户
提问于 2021-11-09 12:06:36
回答 1查看 80关注 0票数 1

因为我是Unix新手,所以我想知道代码是否反映了"unix“风格,以及是否需要添加一些内容来使其健壮。

我希望我没有过度使用assert电话。

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

#include <string.h>
#include <errno.h>
#include <assert.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define whaterror strerror(errno)
#define PORT 0xbb8
#define BACKLOG 0xf // can't be > 128. 
#define BUFFSIZE 0x400

void init_server(struct sockaddr_in* server)
{
    assert(server != NULL && "Server pointer can't be null");

    server -> sin_family = AF_INET; // use IP.
    server -> sin_addr.s_addr = INADDR_ANY; // listen on any address (0.0.0.0).
    server -> sin_port = htons(PORT); // listen on PORT.
}

int main()
{
    struct sockaddr_in sock_in; // an inbound socket
    const int sockfd = socket(PF_INET, SOCK_STREAM, 0); // try to open the socket.
    assert(sockfd >= 0 && "Error in opening socket."); // check if socket opened.
    memset((char*)&sock_in, 0, sizeof(sock_in)); // reset sock_in to 0

    init_server(&sock_in); // initialize server struct
    assert(
        bind(sockfd, (const struct sockaddr*)&sock_in, sizeof(sock_in)) >= 0 &&
        "Port binding failed."
    );
    assert(
        listen(sockfd, BACKLOG) == 0 &&
        "Can't listen to the socket specified."
    );

    int bytes = 0;
    char* chunk = memset(malloc(BUFFSIZE), 0, BUFFSIZE);
    const int asocfd = accept(sockfd, NULL, 0);
    assert(asocfd >= 0 && "Error in accepting socket."); // check if socket opened.

    do {
        bytes = recv(asocfd, chunk, BUFFSIZE - 1, 0);
        memset(bytes == -1 ? chunk : chunk + bytes, 0, BUFFSIZE);
        !errno ?
            bytes && printf("%d\n%s\n", bytes, chunk)
            : fprintf(stderr, "ERRNO: %d [%s]\n", errno, whaterror);
    } while (errno == EAGAIN | bytes > 0);

    return 0;
}
EN

回答 1

Code Review用户

发布于 2021-11-09 17:00:37

我希望我没有过度使用assert调用

你知道的。assert是一种调试工具。如果定义了NDEBUG宏,则在编译时删除对assert的调用。这是生产代码的通常做法。

  • #define whaterror strerror(errno),我建议你不要这么做。宏不添加值,只混淆代码。
  • memset(malloc记住,malloc可能会失败。
  • memset(bytes == -1 ? chunk : chunk + bytes, 0, BUFFSIZE);BUFFSIZE字节设置为0,写入超出分配的空间。你需要BUFFSIZE - bytes。另一方面,没有必要清除chunk的整个尾部。chunk[bytes] = 0;就够了。
  • !errno ?,除了是另一个混淆,是完全错误的。errno是一种检查错误的方法,而不是检测错误的方法。事实上,引用man errno的话,成功的调用永远不会设置errno;一旦设置,它将一直保持到另一个错误发生。recv返回-1是错误的唯一指示。
  • 由于套接字没有标记为非阻塞,它可能永远不会返回EAGAIN。另一方面,一些错误是暂时的,不应该中断循环。
票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

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

复制
相关文章

相似问题

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