【Linux服务器编程总结】网络编程基础知识 (udp初级)

news2024/11/27 11:18:56

一.预备知识

1.主机字节序和网络字节序:

其实本质就是大小端。通常在网络传输的时候会将要发送的数据转同一转换成大端后再发送。在linux中提供了如下四个函数进行大小端转换。

2. 网络套接字:

我们在网络编程的时候会使用到socktet 套接字。对此我们需要了解socket地址也就是结构体socketaddr。一共有两种socketaddr,一种是通用socket地址另一种是专用socket地址。网络编程中常用专用的socket地址。socketaddr结构体也划分成很多种。有用于unix本地下的sockaddr_un,用于tcp/ip的sockaddr_in 和sockaddr_in6。不过在使用socket套接字编程的时候,必须要将专用的socketaddr结构体转换成通用的,因为所有socket编程的接口都是sockaddr。

struct socketaddr_in
{
    sa_family_t sin_family;//地址族一般与协议族保持一致
    u_int16_t sin_port; //端口号
    struct in_addr sin_addr; //ip地址结构体
}

struct in_addr  
{
    u_int32_t s_addr; //ip地址
}

3.ip地址转换函数

通常我们用点分时进制来表示ip比如127.0.0.1。但是从上文中可以知道存放ip的位置只有32位,所以不能用点分时机制直接传。这里我们就可以使用ip地址转换函数将字符串类型的点分时进制转换成网络字节整数了。同业也能通过这类函数进行方向转化。

 4.创建网络套接字:

创建socket。简单说一下三个参数,domain 告诉系统使用那个底层协议族(PF_INET还是PF_UNIX),type是指定服务类型,面向数据流还是数据报。protocal选择具体协议,这个值有钱两个参数确定,通常情况下我们选择0,也就是默认协议。最后会返回给我们一个sockfd描述符

 5.命名网络套接字:

创建完套接字后我们需要socket地址也就是和socketaddr绑定起来。这种行为我们称为命名。通常情况下服务器需要绑定地址,客户端不用手动绑定地址而是由系统自动分配。我们可以用下面这个函数进行命名。

6.udp数据读写:

 这两个参数不仅仅可以用于udp信息的发送和接受,也可以用于tcp的信息传输。buf是要信息的缓冲区,做后两个参数是对段的套接字地址。

 二.结合实例

udp_server.hpp 实现

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <cstdlib>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>

#define SIZE 1024
class udp_server
{
public:
    udp_server(uint16_t port, std::string ip = "")
        : _port(port), _socket(), _ip(ip)
    {
    }
    ~udp_server()
    {
        if (_socket >= 0)
            close(_socket);
    }

    bool initServer()
    {

        // 创建套接字
        _socket = socket(PF_INET, SOCK_DGRAM, 0); // PF_INET和AF_INET值是一样的表示tcp/ip协议族,因为是udp面向数据报所以是dgram
        if (_socket < 0)
        {
            printf("ERROR %d:%s", errno, strerror(errno));
            exit(-1);
        }
        // 命名套接字
        struct sockaddr_in local;
        bzero(&local, sizeof local); // 最好把新定义的空间清零
        // 填充套接字地址
        local.sin_family = PF_INET;
        local.sin_addr.s_addr = _ip.empty() ? INADDR_ANY : inet_addr(_ip.c_str()); // ip最好不要直接绑定成唯一的,否则假如有两个网卡同时接受客户端信息就会有一个网卡收不到信息
                                                                                   //(不同网卡ip不同) 使用inaddrany就是系统自动绑定ip
        local.sin_port = htons(_port);

        int _bd = bind(_socket, (struct sockaddr *)&local, sizeof local);
        if (_bd < 0)
        {
            printf("ERROR %d:%s", errno, strerror(errno));
            exit(-1);
        }
        printf("init udp server done ... %s", strerror(errno));
        return true;
    }

    void start()
    {
        char buffer[SIZE];
        while (1)
        {
            struct sockaddr_in rec; // 输出行参数
            bzero(&rec, sizeof rec);
            // 输入: rec大小
            // 输出: 实际读到的rec 大小
            socklen_t len = sizeof rec;
            ssize_t size = recvfrom(_socket, buffer, sizeof (buffer) -1 , 0, (struct sockaddr *)&rec, &len); // 注意回车不读
            if (size > 0)                                                                              // 获取信息成功
            {
                buffer[size] = 0; // 在获取信息后的最后一个位置添加终止
                printf("%s\n", buffer);
                // 获取客户端套接字地址
                uint16_t cli_port = ntohs(rec.sin_port);
                std::string cli_ip = inet_ntoa(rec.sin_addr);
                std::cout << cli_port << std::endl;
                std::cout << cli_ip << std::endl;
            }
        }
    }

private:
    uint16_t _port;  // 端口号
    int _socket;     // 套接字
    std::string _ip; // ip
};

 udp_server.cc实现

#include "udp_server.hpp"
#include <memory>
#include <cstdlib>
int main (int argc,char *argv[])
{
    if(argc != 2)
    {
        std::cout<<"fail";
        exit(1);
    }
    uint16_t port = atoi(argv[1]);
    std::unique_ptr<udp_server> svr(new udp_server(port));
    svr->initServer();
    svr->start();
    std::cout<<"successful";

    return 0;
}

这样我们就能实现客户端发送信息,服务端收到的一个简单应用了

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/617764.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SQL语句之DQL语言(一)

说明&#xff1a;DQL&#xff08;Data Query Language&#xff0c;数据查询语言&#xff09;&#xff0c;用来查询数据库表中的记录。有的书中&#xff0c;会把DQL语言放入到DML&#xff08;Data Manipulation Language&#xff0c;数据操作语言&#xff1a;数据的增删改&#…

初识TypeScript -基础一

前言 在开始工作之前&#xff0c;就听朋友提过TypeScript&#xff0c;之前也没多想学习&#xff0c;直到vue3出来之后&#xff0c;感觉TypeScript 后面会成为主流&#xff0c;只能硬着头皮学学吧。 读完本片文章&#xff0c;你会收获 1、TypeScript的历史及其优势 2、TypeScri…

Day_39关键路径

目录 一. 关于关键路径 1. 有向无环图 2. AOV网 3. 拓补排序 4. 关键路径 二. 如何实现寻找关键路径 三. 关键路径的代码实现 1. 正向计算 1.1 计算每个节点的入度 1.2 拓扑排序&#xff08;计算每个节点最早开始的时间&#xff09; 2. 反向计算 2.1 计算每个节点的出度&…

基于jupyter的线性回归练习

文章目录 练习1&#xff1a;线性回归介绍1 实现简单示例函数1.1 提交解决方案 2 单变量线性回归2.1 绘制数据2.2 梯度下降2.2.1 更新公式2.2.2 实现2.2.3 计算成本J(θ)2.2.4 梯度下降 2.3 可视化成本函数 选做练习3 多变量线性回归3.1 特征标准化3.2 梯度下降 总结 练习1&…

第六章:多表查询

第六章&#xff1a;多表查询 ​ 多表查询&#xff0c;也称为关联查询&#xff0c;指两个或更多个表一起完成查询操作。 ​ 前提条件&#xff1a;这些一起查询的表之间是有关系的(一对一、一对多)&#xff0c;它们之间一定是有关联字段&#xff0c;这个关联字段可能建立了外键…

SciencePub学术 | 人工智能类重点SCIEI征稿中

SciencePub学术 刊源推荐: 人工智能类重点SCI&EI征稿中&#xff01;影响因子高&#xff0c;对国人友好。信息如下&#xff0c;录满为止&#xff1a; 一、期刊概况&#xff1a; 人工智能类重点SCI&EI 【期刊简介】IF&#xff1a;7.5-8.0&#xff0c;JCR1区&#xff0…

chatgpt赋能python:Python如何获取图片的尺寸

Python如何获取图片的尺寸 如果你在使用Python编程&#xff0c;常常需要获取图片的尺寸&#xff0c;本文将介绍如何使用Python获取图片的尺寸&#xff0c;同时还会介绍一些常用的Python库用于图像处理。 PIL库 PIL&#xff08;Python Imaging Library&#xff09;是Python中…

chatgpt赋能python:Python中如何设置空格

Python中如何设置空格 作为一门流行的编程语言&#xff0c;Python被广泛地应用于各种领域。在编写Python代码时&#xff0c;空格的使用非常重要。适当的空格设置可以让代码易读易懂&#xff0c;同时也有助于提高代码的可维护性和可重用性。 什么是空格 在Python中&#xff0…

shell脚本:循环结束语句二

shell脚本-循环结束语句二 二、循环结束语句&#xff1a;1.break&#xff1a;跳出循环。2.continue&#xff1a;3.while&#xff1a;4.until&#xff1a;条件不成立时&#xff0c;跳出循环。5.总结&#xff1a; 三、操作演练&#xff1a; 二、循环结束语句&#xff1a; 1.brea…

QT CTK插件开发(六) 多对一插件

CTK在软件的开发过程中可以很好的降低复杂性、使用 CTK Plugin Framework 提供统一的框架来进行开发增加了复用性 将同一功能打包可以提供多个应用程序使用避免重复性工作、可以进行版本控制提供了良好的版本更新迭代需求、并且支持动态热拔插 动态更新、开发更加简单快捷 方便…

基于jupyter的逻辑回归练习

文章目录 练习2&#xff1a;逻辑回归介绍1 Logistic回归1.1 数据可视化1.2 实现1.2.1 Sigmoid函数1.2.2 代价函数和梯度1.2.2.1 代价函数1.2.2.2 梯度下降 1.2.3 寻找最优参数1.2.4 评估逻辑回归 2 正则化逻辑回归2.1 数据可视化2.2 特征映射2.3 代价函数和梯度 2.4 寻找最优参…

腾讯云618云服务器优惠活动价格表

2023年腾讯云618年中促销活动已经正式开始了&#xff0c;腾讯云多款云服务都有特惠&#xff0c;下面给大家分享腾讯云618云服务器优惠活动价格表&#xff0c;记得抓住这次上云好时机&#xff01; 目录 一、腾讯云618活动入口 二、轻量应用服务器优惠价格表 三、CVM云服务器优…

【连续介质力学】二阶张量的图像表示

二阶张量在特定方向的投影 法向和切向分量 二阶张量T投影到 n ^ \hat n n^方向的结果是 t ⃗ ( n ^ ) T ⋅ n ^ \vec t^{(\hat n)}T \cdot \hat n t (n^)T⋅n^&#xff0c;其中 t ⃗ ( n ^ ) \vec t^{(\hat n)} t (n^)可以分解成&#xff1a; t ⃗ ( n ^ ) T ⃗ N T ⃗ S…

指针(三)

文章内容 1. 字符指针 2. 数组指针 3. 指针数组 文章内容 1. 字符指针 指针的概念&#xff1a; 1. 指针就是个变量&#xff0c;用来存放地址&#xff0c;地址唯一标识一块内存空间。 2. 指针的大小是固定的4/8个字节&#xff08;32位平台/64位平台&#xff09;。 3. 指针…

适配器stack和queue

目录 什么是适配器 模拟实现stack stack的特性 STL中stack的基本框架 接口实现 模拟实现queue queue的特性 STL中queue的框架 什么是适配器 适配器&#xff1a;所谓适配&#xff0c;适配的是容器(vector,list,deque....) 也就是不管是什么容器&#xff0c;都可以套用适…

chatgpt赋能python:Python如何设置输入的SEO

Python如何设置输入的SEO Python是一种高级的编程语言&#xff0c;具有容易上手、可扩展和开源等特点&#xff0c;因此在软件开发过程中得到广泛的应用。然而&#xff0c;如果您想让您的Python项目在搜索引擎上获得更好的排名和流量&#xff0c;您需要考虑如何设置输入的SEO。…

二叉搜索树(Binary Seach Tree)模拟实现

目录 二叉搜索树的性质 二叉搜索树的实现 结点类 接口类(BSTree) 二叉搜索树的插入(insert) 二叉搜索树的查找(find) 二叉搜索树删除(erase) 第二种、删除的结点右子树为空 第三种、删除的结点左子树为空 第四种、删除的结点左右都不为空 实现 二叉搜索树模拟实现代…

基于jupyter的轮廓检测及功能

文章目录 一、实验介绍二、实验步骤三、实验任务任务一&#xff1a;轮廓特征练习一: 找到每个轮廓的方向任务二&#xff1a;边界矩形练习二: 围绕轮廓裁剪图像 总结 一、实验介绍 1. 实验内容 本实验将学习轮廓检测及功能。 2. 实验要点 生成二进制图像来查找轮廓找到并画出…

kotlin函数返回函数

kotlin函数返回函数 https://blog.csdn.net/zhangphil/category_12220817.htmlhttps://blog.csdn.net/zhangphil/category_12220817.html 例1&#xff1a; // func返回匿名函数 fun func(msg: String): (String, Int) -> String {println("func函数 msg:$msg")/…

电能管理系统多功能电力仪表的应用 安科瑞 许敏

摘 要&#xff1a;基于车间用电设备的电能管理系统架构思路及实施方法&#xff0c;从硬件和软件方面对此方法进行了阐述。对车间旧设备改造以及新的电能管理系统提供一种思路和便捷的方法。 关键词&#xff1a;电能管理系统&#xff1b;多功能电力仪表&#xff1b;PLC&#x…