当前位置: 首页 > news >正文

Linux网络编程概述

Linux网络编程是在Linux操作系统环境下进行的网络相关程序开发,主要用于实现不同计算机之间的数据通信和资源共享。以下从基础知识、网络编程模型、常用函数和编程步骤等方面进行详细介绍:

基础知识

1. 网络协议

  • TCP/IP协议族:是互联网通信的基础协议,包括多个层次的协议。例如,IP协议负责网络层的数据包传输,TCP和UDP协议则工作在传输层。

    • TCP(传输控制协议):提供面向连接、可靠的、基于字节流的传输服务。在进行数据传输前需要建立连接,传输完成后需要断开连接,适合对数据准确性要求较高的场景,如文件传输、网页浏览等。

    • UDP(用户数据报协议):提供无连接、不可靠的传输服务。不需要建立连接,数据以数据报的形式发送,适合对实时性要求较高、对数据准确性要求相对较低的场景,如视频会议、实时游戏等。

2. 网络地址

  • IP地址:用于唯一标识网络中的设备,分为IPv4和IPv6两种。IPv4地址由32位二进制数组成,通常表示为点分十进制形式,如192.168.1.1;IPv6地址由128位二进制数组成,采用冒号分隔的十六进制表示。

  • 端口号:用于区分同一设备上不同的网络应用程序,范围从0到65535。其中,0 - 1023为系统保留端口,通常由系统服务使用,如HTTP服务默认使用80端口,HTTPS服务默认使用443端口。

网络编程模型

1. 客户端 - 服务器模型

  • 这是最常见的网络编程模型,由客户端和服务器两部分组成。服务器监听特定的端口,等待客户端的连接请求;客户端主动发起连接请求,与服务器建立连接后进行数据交互。

2. 多进程/多线程模型

  • 多进程模型:服务器为每个客户端连接创建一个新的进程来处理,各个进程之间相互独立,一个进程的崩溃不会影响其他进程。但创建和销毁进程的开销较大,会消耗较多的系统资源。

  • 多线程模型:服务器为每个客户端连接创建一个新的线程来处理,线程共享进程的资源,创建和销毁线程的开销相对较小。但线程之间的同步和互斥问题需要处理,否则可能会出现数据不一致的情况。

3. I/O多路复用模型

  • 使用selectpollepoll等函数,让一个进程可以同时监听多个文件描述符(包括网络套接字)的读写事件,当某个文件描述符有事件发生时,通知进程进行相应的处理。这种模型可以提高服务器的并发处理能力,减少系统资源的消耗。

常用函数

1. 套接字相关函数

  • socket():用于创建一个套接字,返回一个文件描述符。例如:

#include <sys/socket.h>
int sockfd = socket(AF_INET, SOCK_STREAM, 0);

其中,AF_INET表示使用IPv4地址族,SOCK_STREAM表示使用TCP协议。

  • bind():将套接字与指定的IP地址和端口号绑定。例如:

#include <arpa/inet.h>
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(8888);
bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
  • listen():将套接字设置为监听状态,等待客户端的连接请求。例如:

listen(sockfd, 5);

其中,5表示允许的最大连接请求队列长度。

  • accept():接受客户端的连接请求,返回一个新的套接字描述符用于与客户端进行通信。例如:

struct sockaddr_in client_addr;
socklen_t client_addr_len = sizeof(client_addr);
int connfd = accept(sockfd, (struct sockaddr *)&client_addr, &client_addr_len);
  • connect():客户端使用该函数向服务器发起连接请求。例如:

struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
server_addr.sin_port = htons(8888);
connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));

2. 数据读写函数

  • send()/recv():用于TCP套接字的数据发送和接收。例如:

// 发送数据
char *msg = "Hello, server!";
send(sockfd, msg, strlen(msg), 0);

// 接收数据
char buffer[1024];
int n = recv(sockfd, buffer, sizeof(buffer), 0);
  • sendto()/recvfrom():用于UDP套接字的数据发送和接收,需要指定目标地址。例如:

// 发送数据
struct sockaddr_in server_addr;
// 初始化server_addr
sendto(sockfd, msg, strlen(msg), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));

// 接收数据
struct sockaddr_in client_addr;
socklen_t client_addr_len = sizeof(client_addr);
int n = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&client_addr, &client_addr_len);

编程步骤

1. 服务器端编程步骤

  1. 创建套接字(socket())。

  2. 绑定套接字到指定的IP地址和端口号(bind())。

  3. 将套接字设置为监听状态(listen())。

  4. 接受客户端的连接请求(accept())。

  5. 与客户端进行数据交互(send()/recv())。

  6. 关闭套接字(close())。

2. 客户端编程步骤

  1. 创建套接字(socket())。

  2. 向服务器发起连接请求(connect())。

  3. 与服务器进行数据交互(send()/recv())。

  4. 关闭套接字(close())。

示例代码

以下是一个简单的TCP服务器和客户端示例代码:

服务器端代码(server.c)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>

#define PORT 8888

int main() {
    int sockfd, connfd;
    struct sockaddr_in server_addr, client_addr;
    socklen_t client_addr_len = sizeof(client_addr);
    char buffer[1024];

    // 创建套接字
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    // 初始化服务器地址结构
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(PORT);

    // 绑定套接字
    if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }

    // 监听套接字
    if (listen(sockfd, 5) == -1) {
        perror("listen failed");
        exit(EXIT_FAILURE);
    }

    printf("Server listening on port %d...\n", PORT);

    // 接受客户端连接
    connfd = accept(sockfd, (struct sockaddr *)&client_addr, &client_addr_len);
    if (connfd == -1) {
        perror("accept failed");
        exit(EXIT_FAILURE);
    }

    printf("Client connected.\n");

    // 接收客户端数据
    int n = recv(connfd, buffer, sizeof(buffer), 0);
    if (n == -1) {
        perror("recv failed");
        exit(EXIT_FAILURE);
    }

    buffer[n] = '\0';
    printf("Received from client: %s\n", buffer);

    // 发送响应数据
    char *msg = "Hello, client!";
    send(connfd, msg, strlen(msg), 0);

    // 关闭套接字
    close(connfd);
    close(sockfd);

    return 0;
}

客户端代码(client.c)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>

#define SERVER_IP "127.0.0.1"
#define PORT 8888

int main() {
    int sockfd;
    struct sockaddr_in server_addr;
    char buffer[1024];

    // 创建套接字
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    // 初始化服务器地址结构
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
    server_addr.sin_port = htons(PORT);

    // 连接服务器
    if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
        perror("connect failed");
        exit(EXIT_FAILURE);
    }

    printf("Connected to server.\n");

    // 发送数据
    char *msg = "Hello, server!";
    send(sockfd, msg, strlen(msg), 0);

    // 接收服务器响应
    int n = recv(sockfd, buffer, sizeof(buffer), 0);
    if (n == -1) {
        perror("recv failed");
        exit(EXIT_FAILURE);
    }

    buffer[n] = '\0';
    printf("Received from server: %s\n", buffer);

    // 关闭套接字
    close(sockfd);

    return 0;
}

文章转载自:
http://chloe.apjjykv.cn
http://assaulter.apjjykv.cn
http://beauteously.apjjykv.cn
http://bolo.apjjykv.cn
http://amphitheater.apjjykv.cn
http://balsam.apjjykv.cn
http://camille.apjjykv.cn
http://antimagnetic.apjjykv.cn
http://axite.apjjykv.cn
http://acanthocephalan.apjjykv.cn
http://boblet.apjjykv.cn
http://axil.apjjykv.cn
http://blackly.apjjykv.cn
http://brigade.apjjykv.cn
http://bode.apjjykv.cn
http://caecostomy.apjjykv.cn
http://bigot.apjjykv.cn
http://ascending.apjjykv.cn
http://blazonry.apjjykv.cn
http://chatterbox.apjjykv.cn
http://avignon.apjjykv.cn
http://alice.apjjykv.cn
http://bandanna.apjjykv.cn
http://antithyroid.apjjykv.cn
http://archaeological.apjjykv.cn
http://bussbar.apjjykv.cn
http://amyotrophy.apjjykv.cn
http://apotropaism.apjjykv.cn
http://arability.apjjykv.cn
http://brethren.apjjykv.cn
http://www.dtcms.com/a/101224.html

相关文章:

  • ISATAP自动隧道
  • web自动化第一步:安装浏览器和驱动(Chrome和ChromeDriver)
  • 【Java】字符串String类
  • 相似度计算 第33次CCF-CSP计算机软件能力认证
  • 分秒计数器设计
  • XPath、XQuery 以及 XSLT 函数
  • 【工具变量】上市公司供应链稳定性数据两个维度(2013-2023年)
  • Netty源码—10.Netty工具之时间轮二
  • 【已开源】UniApp+vue3跨端应用从0到1开发指南、uniapp+vue3模板应用
  • 生成和管理作品集链接
  • Trae-中国首款免费AI原生IDE
  • Router [Continuation Settings]
  • 打包python文件生成exe
  • 【C++】 string底层封装的模拟实现
  • 【蓝桥杯】每日练习 Day 16,17
  • GO语言杂记(文章持续更新)
  • PostgreSQL15深度解析(从15.0-15.12)
  • 打造高性能中文RAG系统:多轮对话与语义检索的完美结合
  • vulhub靶场—— Tomcat8
  • vue3搭建实战项目笔记三
  • 如何设置PDF文件的到期日期
  • this关键字
  • 特征增强金字塔FPN
  • 为什么 ThreadLocalMap 的 key 是弱引用 value是强引用
  • 过滤器filter,监听器Listener
  • Java日志进化论:从System.out.println到日志框架的全面升级
  • 青少年编程与数学 02-013 初中数学知识点 02课题、概要
  • 习题2.1
  • 【免费】2007-2019年各省地方财政医疗卫生支出数据
  • J2EE框架技术 第三章 SSM项目的CURD