C语言实现 网络通信 Network

在现代计算机网络中,网络通信是不可或缺的一部分。本文将介绍如何使用C语言实现一个简单的网络通信库,涵盖TCP和UDP协议的基本功能。我们将通过一个示例代码库进行详细讲解,以便更好地理解网络编程的核心概念。

项目结构

本项目包含两个文件:

  • network.h:头文件,定义了数据结构和函数原型。
  • network.c:实现文件,包含具体的网络通信功能。

1. 关键结构体

network.h中,我们定义了一个Network结构体,包含以下字段:

typedef struct Network
{
    int type;  // 通信协议类型
    int sock_fd; // socket描述符
    struct sockaddr_in addr; // 通信地址
    socklen_t addrlen; // 通信地址字节数
    bool issvr; // 是否是服务器
} Network;

2. 初始化网络

init_nw函数是这个网络库的核心,用于创建socket并初始化地址。根据传入的参数(是否为服务器,协议类型等),该函数执行不同的初始化操作。

Network *init_nw(int type, short port, const char *ip, bool issvr)
{
    Network *nw = malloc(sizeof(Network));
    nw->sock_fd = socket(AF_INET, type, 0);
    if (nw->sock_fd < 0) {
        free(nw);
        perror("socket");
        return NULL;
    }
    bzero(&nw->addr, nw->addrlen);
    nw->type = type;
    nw->issvr = issvr;
    nw->addr.sin_family = AF_INET;
    nw->addr.sin_port = htons(port);
    nw->addr.sin_addr.s_addr = inet_addr(ip);
    nw->addrlen = sizeof(struct sockaddr_in);

    if (issvr) {
        if (bind(nw->sock_fd, (SP)&nw->addr, nw->addrlen)) {
            free(nw);
            perror("bind");
            return NULL;
        }
        if (SOCK_STREAM == type && listen(nw->sock_fd, 50)) {
            free(nw);
            perror("listen");
            return NULL;
        }
    } else if (SOCK_STREAM == type) { // TCP客户端
        if (connect(nw->sock_fd, (SP)&nw->addr, nw->addrlen)) {
            free(nw);
            return NULL;
        }
    }

    return nw;
}

3. 等待连接

accept_nw函数用于TCP服务器端,等待客户端的连接请求。它检查当前Network对象是否为服务器类型,并返回新的连接对象。

Network *accept_nw(Network* svr_nw)
{
    if (SOCK_STREAM != svr_nw->type || !svr_nw->issvr) {
        printf("只有tcp协议的服务器端的NETWORK对象可以使用");
        return NULL;
    }

    Network *nw = malloc(sizeof(Network));
    nw->addrlen = svr_nw->addrlen;
    nw->type = SOCK_STREAM;
    nw->issvr = true;
    nw->sock_fd = accept(svr_nw->sock_fd, (SP)&nw->addr, &nw->addrlen);

    if (nw->sock_fd < 0) {
        free(nw);
        perror("accept");
        return NULL;
    }

    return nw;
}

4. 发送与接收数据

send_nwrecv_nw函数分别用于发送和接收数据。根据协议类型,这两个函数会采用不同的方法处理数据。

int send_nw(Network *nw, void* buf, size_t len)
{
    if (nw->type == SOCK_DGRAM) {
        return sendto(nw->sock_fd, buf, len, 0, (SP)&nw->addr, nw->addrlen);
    } else {
        return send(nw->sock_fd, buf, len, 0);
    }
}

int recv_nw(Network *nw, void* buf, size_t len)
{
    if (nw->type == SOCK_DGRAM) {
        return recvfrom(nw->sock_fd, buf, len, 0, (SP)&nw->addr, &nw->addrlen);
    } else {
        return recv(nw->sock_fd, buf, len, 0);
    }
}

5. 关闭连接

close_nw函数用于关闭socket并释放内存,确保资源得到有效管理。

void close_nw(Network *nw)
{
    close(nw->sock_fd);
    free(nw);
}

6. 获取IP地址

getip_nw函数用于获取并返回与网络对象关联的IP地址。

const char *getip_nw(Network *nw)
{
    return inet_ntoa(nw->addr.sin_addr);
}

总结

通过这种模块化的设计,我们实现了一个简单而强大的网络通信库,易于扩展和维护。用户只需调用高层函数即可实现复杂的网络通信,极大提高了开发效率。这种封装和结构化的写法不仅使代码更易于阅读和理解,还能有效避免常见的错误。希望本文能够为你的网络编程实践提供帮助和启发!

4o

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值