首页 > 系统相关 >linux系统网络编程

linux系统网络编程

时间:2024-08-10 16:52:01浏览次数:12  
标签:HTTP addr 编程 网络 client linux 接字 include socket

 网络核心概念

网络: 通过有线或无线的链路连接多个计算机设备进行数据通信或设备控制

介质:双绞线,同轴电缆,光纤

无线: WIFL ,移动网络,蓝牙,红外,NFC

设备: 计算机,交换机,路由器,IOT

在网络编程中,应用层协议编程是非常关键的一部分,因为它直接涉及到了如何在不同的应用程序之间交换数据。这里我们将详细讨论如何基于TCP和UDP在应用层进行编程,特别是以HTTP协议为例(HTTP是基于TCP的应用层协议)。

TCP/IP 应用层编程

1. TCP编程

TCP(传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。在TCP编程中,我们通常使用套接字(Socket)来实现网络通信。

TCP 客户端编程步骤

  1. 创建套接字:使用socket()函数创建一个新的套接字。
  2. 连接到服务器:使用connect()函数将套接字连接到服务器。
  3. 发送和接收数据:使用send()recv()函数发送和接收数据。
  4. 关闭套接字:使用close()函数关闭套接字。
//client
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>



int main(int argc, char const *argv[])
{
    //创建套接字
    //1. 域
    //2. 套接字类型
    //3. 协议
    int socket_fd =socket(AF_INET,SOCK_STREAM,0);
    if(socket_fd == -1)
    {
        printf("socket erro!\n");
        return EXIT_FAILURE;
    }



    //连接服务器
    //1. 套接字
    //2. 目标地址
    //3. 目标地址长度
    struct  sockaddr_in addr; //unix
    addr.sin_family = AF_INET;
    addr.sin_port = htons(9000);
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");

  
    int res =connect(socket_fd,(const struct sockaddr *)&addr,sizeof(addr));
    if(res == -1)
    {
        printf("connect erro!\n");
        return EXIT_FAILURE;
    }

    char ch[32] ;
    for(int i=0;i<9;i++)
    {

    printf("pelese insert your words limit 31\n");
    fgets(ch,32,stdin);
    //去除字尾部符号
    
    //读写数据
    
    write(socket_fd,ch,sizeof(ch));
    printf("已经发送数据%s\n",ch);
    read(socket_fd,ch,sizeof(ch));
    printf("接受到:%s\n",ch);
       
    }
   
    
    
    close(socket_fd);
    return 0;
}

TCP 服务器编程步骤

  1. 创建套接字:同样使用socket()函数。
  2. 绑定套接字:使用bind()函数将套接字绑定到一个特定的IP地址和端口上。
  3. 监听连接:使用listen()函数使套接字进入被动监听状态,等待客户端的连接请求。
  4. 接受连接:使用accept()函数接受客户端的连接请求,并为每个连接创建一个新的套接字。
  5. 发送和接收数据:使用send()recv()函数与客户端进行通信。
  6. 关闭套接字:关闭连接和套接字。
// server.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>

int main(int argc, char const *argv[])
{
    // 创建套接字
    int socket_server = socket(AF_INET, SOCK_STREAM, 0);

    // 服务地址 端口号9000
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(9000);
    // 服务器
    server_addr.sin_addr.s_addr = INADDR_ANY;

    // 绑定地址
    
    bind(socket_server, (struct sockaddr *)&server_addr, sizeof(server_addr));

    // 监听
    listen(socket_server, 5);
    printf("服务器启动\n");

    //    struct sockaddr_un addr_client;
    //    addr_client.sun_family = AF_UNIX;
    //    socklen_t addr_len = sizeof(addr_client);
    // 接收请求 可写死循环,或者其他条件
    struct sockaddr_in addr_client;
    addr_client.sin_family = AF_INET;
    int addr_len = sizeof(addr_client);
    // //子进程结束
    signal(SIGCHLD, SIG_IGN);

    while (1)
    {
        printf("服务器等待客户端请求\n");
        // 接受请求,建立了TCP连接,获得了一个新的客户端套接字
        int socket_client = accept(
            socket_server,
            (struct sockaddr *)&addr_client,
            &addr_len);

        if (socket_client == -1)
        {
            printf("连接失败\n");
            return EXIT_FAILURE;
        }
        // 获得一个套接字标识符可以交给进程和线程灵活处理
        // 并发
        //  异步
        //  开启多进程

        if (fork() == 0)
        {
            int pid = getpid();
            char buf[32];
            for (size_t i = 0; i < 9; i++)
            {
                read(socket_client, buf, 32);
                printf("%d 收到 %ld,%s\n", pid, i, buf);

                char msg[32] = "bye tcp!";
                write(socket_client, msg, 32);
            }
            // 进程退出
            exit(EXIT_SUCCESS);
        }
        else
        {

            close(socket_client);
        }

        // 对请求做响应
        // char buf[1024];

        // read(socket_client,buf,sizeof(buf));
        // //收到数据你可以查询数据库等操作
        // printf("收到%s\n",buf);

        // // strcpy(buf,"BYE TCP\n");
        // write(socket_client,&buf,sizeof(buf));
    }

    return 0;
}
2. UDP编程

UDP(用户数据报协议)是一个简单的面向数据报的传输层协议。与TCP不同,UDP不提供可靠的数据传输服务,不保证数据包的顺序、到达或不重复。

UDP 客户端和服务器编程步骤类似

  1. 创建套接字:使用socket()函数,但指定协议为UDP。int sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { perror("socket creation failed"); exit(EXIT_FAILURE); }
  2. int sockfd = socket(AF_INET, SOCK_DGRAM, 0);  
    if (sockfd < 0) {  
        perror("socket creation failed");  
        exit(EXIT_FAILURE);  
    }
  3. 绑定套接字(可选):对于服务器,使用bind()函数将套接字绑定到一个特定的IP地址和端口上。客户端通常不需要绑定。
  4. struct sockaddr_in serv_addr;  
    memset(&serv_addr, 0, sizeof(serv_addr));  
    serv_addr.sin_family = AF_INET;  
    serv_addr.sin_addr.s_addr = INADDR_ANY; // 或者指定一个具体的IP地址  
    serv_addr.sin_port = htons(PORT); // PORT是服务器监听的端口号  
      
    if (bind(sockfd, (const struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {  
        perror("bind failed");  
        exit(EXIT_FAILURE);  
    }
  5. 发送和接收数据:使用sendto()recvfrom()函数发送和接收数据。注意,由于UDP是无连接的,sendto()recvfrom()函数都需要指定目标地址和端口(发送时)或来源地址和端口(接收时)。
  6. struct sockaddr_in client_addr;  
    memset(&client_addr, 0, sizeof(client_addr));  
    client_addr.sin_family = AF_INET;  
    client_addr.sin_addr.s_addr = inet_addr("目标IP地址");  
    client_addr.sin_port = htons(目标端口号);  
      
    ssize_t num_bytes_sent = sendto(sockfd, buffer, strlen(buffer), 0,  
                                    (const struct sockaddr *)&client_addr, sizeof(client_addr));  
    if (num_bytes_sent < 0) {  
        perror("sendto failed");  
        exit(EXIT_FAILURE);  
    }
  7. 关闭套接字:使用close()函数关闭套接字。
  8. close(sockfd);
     

HTTP协议编程

HTTP(超文本传输协议)是基于TCP的应用层协议,用于在Web服务器和客户端之间传输超文本。在HTTP编程中,我们通常不直接实现HTTP协议,而是使用现成的库或框架来处理HTTP请求和响应。

HTTP 客户端编程

  • 使用HTTP客户端库(如Python的requests库)发送HTTP请求。
  • 接收HTTP响应并处理响应内容。

HTTP 服务器编程

  • 使用Web服务器软件(如Apache, Nginx)或编写自定义的HTTP服务器。
  • 解析HTTP请求,处理请求并生成HTTP响应。
  • 发送HTTP响应给客户端。

标签:HTTP,addr,编程,网络,client,linux,接字,include,socket
From: https://blog.csdn.net/m0_61832483/article/details/141092808

相关文章

  • linux系统磁盘管理
    linux系统磁盘管理硬盘命名在设备名称的定义规则如下,其他的分区可以以此类推系统的第⼀块SCSI接⼝的硬盘名称为/dev/sda系统的第⼆块SCSI接⼝的硬盘名称为/dev/sdb系统中分区由数字编号表示,1~4留给主分区使⽤和扩展分区,逻辑分区从5开始有些存放数据的设备并不是直接......
  • Linux内核解读(1)--内存管理与malloc原理
        本文主要关注Linux环境的堆内存的管理,详细解析Glibc与TCMalloc的malloc原理, 由于本人能力有限,难免会出现解读错误的地方,望各位大佬批评指正,后面也会在进一步解读中对本文进行修改。1、Linux内存分布        下图的布局形式是在内核2.6.7以后才引入的,......
  • Linux问题调试(4)--内存问题与tcmalloc
    1、问题概述      之前的文章介绍过Asan来定位内存泄漏问题,虽然已经被集成到各大编译器中,‌但它的使用可能受到特定环境或配置的限制。‌例如,‌在某些复杂的系统或应用程序中,‌ASan可能会因为与程序的交互复杂性而遇到挑战,‌导致难以准确诊断问题。‌Linux问题调试(2)--......
  • 网络编程基础
    目录学习内容:1. 网络体系结构及OSI开放系统系统互联模型1.1 网络体系结构概念 1.2 OSI开放系统互联模型1.3 TCP/IP协议族(簇)的体系结构1.4 TCP/IP四层结构中常见的协议 2. TCP和UDP异同(笔试面试)3.网络编程基础相关的概念3.1 字节序2>验证主机大小端的方......
  • 使用Linux实现FTP云盘项目2
    实现功能:ls———查看服务端文件lls———查看客户端自己的文件cd———切换服务端目录lcd———切换客户端自己的目录切换成功put———上传文件get———下载文件服务器端:客户端:源码:#include<sys/types.h>/*SeeNOTE......
  • 详解linux后台、前台运行进程
    程序运行可以有2种前台运行程序运行在当前的终端,所有的信息都输出到屏幕上,占用你的终端,你也无法继续使用如果终端异常关闭,导致程序会自动退出后台运行不会占用你的终端,程序在系统后台跑着,你该干啥干啥,终端关了,程序也继续运行。后台运行命令命令集合command&#未启动......
  • Linux计划任务
    Linux计划任务Linux计划任务是系统管理和自动化的重要工具,可以减少人工干预、提高工作效率,并有效管理系统资源和维护。使用恰当的工具,可以显著提升系统的可靠性和运行效率。1.一次性计划任务at1.1下载安装yum-yinstallat#yum下载安装systemctlstartatd......
  • Python网络爬虫抓取动态网页并将数据存入数据库MySQL
    简述以下的代码是使用python实现的网络爬虫,抓取动态网页http://hb.qq.com/baoliao/。此网页中的最新、精华下面的内容是由JavaScript动态生成的。审查网页元素与网页源码是不同。以上是网页源码以上是审查网页元素所以此处不能简单的使用正则表达式来获取内容。......
  • C#多线程并发编程深度探索:解锁async、await、Task与lock等关键字的奥秘
    一、多线程介绍1.什么是多线程多线程是指在一个应用程序中同时执行多个线程的能力。每个线程都是独立运行的,拥有自己的执行路径和资源。多线程编程能够充分利用多核处理器的计算能力,提高应用程序的性能和响应性,特别是在处理耗时任务和并行计算时效果显著。在C#中,线程是程序......
  • 零基础转行网络安全真的好就业吗?(非常详细)零基础入门到精通,收藏这一篇就够了
    网络安全作为近两年兴起的热门行业,成了很多就业无门但是想转行的人心中比较向往但是又心存疑惑的行业,毕竟网络安全的发展史比较短,而国内目前网安的环境和市场情况还不算为大众所知晓,所以到底零基础转行入门网络安全之后,好不好就业呢?今天我们就来全面彻底分析一下网络安全对......