linux 网络编程-基础篇
发布日期:2021-05-10 04:47:50 浏览次数:21 分类:精选文章

本文共 3731 字,大约阅读时间需要 12 分钟。

Socket编程简介

Socket是网络编程中的一个核心概念,它允许应用程序在不同计算机之间进行数据通信。在Unix系统中,所有网络操作都以文件描述符的形式呈现,Socket并非专指TCP/IP协议,而是支持多种网络协议,包括TCP、UDP和IPX。

Socket类型

Socket根据其功能和使用的协议可以分为以下几种类型:

  • 流式Socket (SOCK_STREAM)

    流式Socket提供面向连接的可靠数据传输服务。数据传输具有无差错、无重复、按顺序接收的特点,适合需要可靠通信的场景。数据被视为字节流,无长度限制,并支持流量控制和拥塞控制。

  • 数据报Socket (SOCK_DGRAM)

    数据报Socket支持无连接通信。数据以独立数据包形式发送,不提供可靠性保证,可能会出现丢失、重复或顺序混乱的问题。这种类型适合实时性要求较高但可容忍数据损失的场景。

  • 原始Socket (SOCK_RAW)

    原始Socket允许应用程序直接访问底层协议,如IP和ICMP。这种类型通常用于需要处理网络层协议的高级程序。

  • IP地址

    IP地址是Internet中主机的唯一标识,每台主机在通信时必须使用一个IP地址。IP地址分为IPv4(32位)和IPv6(128位)两种形式。每个数据包都携带源IP地址和目的IP地址,路由器根据这些地址为数据包选择路由。

    字节序转换

    在网络编程中,字节序转换是常见操作。由于不同操作系统使用不同的字节序(小端序或大端序),网络传输的数据必须统一使用网络字节序(通常是大端序)。应用程序在发送数据前需要将主机字节序转换为网络字节序,在接收数据后再转换回主机字节序。常用的转换函数包括htonlhtonsntohlntohs

    网络编程API

    以下是常用的网络编程API:

    • socket():创建Socket。
    • bind():将Socket绑定到指定IP地址和端口。
    • listen():设置Socket监听模式。
    • accept():接收来自其他主机的连接请求。
    • connect():建立与远程主机的连接。
    • send()recv():发送和接收数据。

    地址结构

    在使用Socket时,需定义socklen_t类型的变量来存储地址长度,并使用sockaddr_in结构体表示IP地址和端口。使用步骤如下:

  • 定义一个sockaddr_in变量并清空:

    struct sockaddr_in myaddr;
    memset(&myaddr, 0, sizeof(myaddr));
  • 填充地址信息:

    myaddr.sin_family = PF_INET;  // 设置家庭协议类型
    myaddr.sin_port = htons(8888); // 设置端口号,使用网络字节序
    myaddr.sin_addr.s_addr = inet_addr("192.168.1.100"); // 设置IP地址
  • 使用bind()函数将Socket绑定到该地址:

    bind(sockfd, (struct sockaddr *)&myaddr, sizeof(myaddr));
  • 客户端代码示例

    #include 
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #define N 64 int main(int argc, char *argv) { if (argc < 3) { printf("使用: %s ip port\n", argv[0]); return -1; } int sockfd; struct sockaddr_in myaddr, peeraddr; char buf[N] = {0}; size_t n; socklen_t mylen, peerlen; mylen = sizeof(myaddr); peerlen = sizeof(peeraddr); if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket"); return -1; } bzero(&myaddr, sizeof(myaddr)); myaddr.sin_family = AF_INET; myaddr.sin_port = htons(atoi(argv[2]) + 1); myaddr.sin_addr.s_addr = inet_addr(argv[1]); if (bind(sockfd, (struct sockaddr *)&myaddr, mylen) < 0) { perror("bind"); return -1; } bzero(&peeraddr, sizeof(peeraddr)); peeraddr.sin_family = AF_INET; peeraddr.sin_port = htons(atoi(argv[2])); peeraddr.sin_addr.s_addr = inet_addr(argv[1]); while (1) { fgets(buf, N, stdin); printf("buf: %s", buf); if (sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *)&peeraddr, peerlen) < 0) { perror("sendto"); return -1; } if (strncmp(buf, "quit", 4) == 0) { break; } printf("n = %d\n", n); } close(sockfd); return 0; }

    服务器代码示例

    #include 
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #define N 64 int main(int argc, char *argv) { if (argc < 3) { printf("使用: %s ip port\n", argv[0]); return -1; } int listenfd, connfd; struct sockaddr_in myaddr, peeraddr; char buf[N] = {0}; size_t n; socklen_t mylen, peerlen; mylen = sizeof(myaddr); peerlen = sizeof(peeraddr); if ((listenfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket"); return -1; } bzero(&myaddr, mylen); myaddr.sin_family = PF_INET; myaddr.sin_port = htons(atoi(argv[2])); inet_aton(argv[1], &myaddr.sin_addr); if (bind(listenfd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) { perror("bind"); return -1; } listen(listenfd, 5); if ((connfd = accept(listenfd, (struct sockaddr *)&peeraddr, &peerlen)) < 0) { perror("accept"); return -1; } printf("连接来自: %s:%d\n", inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port)); while (1) { n = recv(connfd, buf, N, 0); buf[n] = 0; printf("n = %d---%s\n", n, buf); if (strncmp(buf, "quit", 4) == 0) { break; } send(connfd, buf, strlen(buf), 0); } close(connfd); close(listenfd); return 0; }

    以上代码示例展示了客户端和服务器在UDP协议下的通信流程,适用于需要实时数据传输的场景。

    上一篇:IP地址转换函数
    下一篇:TCP协议中的端口具体指的是什么,为什么要有端口,你是怎么理解的?

    发表评论

    最新留言

    逛到本站,mark一下
    [***.202.152.39]2025年04月01日 00时25分45秒

    关于作者

        喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
    -- 愿君每日到此一游!

    推荐文章