【网络】网络编程套接字

一、知识提及

1.源IP地址和目的IP地址

在IP数据包头部中, 有两个IP地址, 分别叫做源IP地址, 和目的IP地址

2.端口号

端口号(port)是传输层协议的内容. 

  • 端口号是一个2字节16位的整数;
  • 端口号用来标识一个进程, 告诉操作系统, 当前的这个数据要交给哪一个进程来处理;
  • IP地址 + 端口号能够标识网络上的某一台主机的某一个进程;
  • 一个端口号只能被一个进程占用.

我们网络通信的本质就是进程间通信,不过是在不同的主机上。

IP地址能标识唯一的一台主机,端口号port可以用来标识主机上唯一的一个进程。

IP :Port = 标识全网唯一的一个进程。

用客户端ip:客户端端口号和服务端ip:服务端端口号的通信就是socket

pid 表示唯一一个进程; 此处我们的端口号也是唯一表示一个进程. 那么这两者之间是怎样的关系?

  1. 不是所有的进程都要网络通信,但是所有进程都要有pid。
  2. 系统和网络功能解耦

源端口号和目的端口号

传输层协议(TCP和UDP)的数据段中有两个端口号, 分别叫做源端口号和目的端口号. 就是在描述 "数据是谁发的, 要发给谁";

一个进程可以绑定多个端口号吗?一个端口号可以被多个进程绑定吗? 

一个进程可以绑定多个端口号。

一个端口号不可以被多个进程绑定。

 3.TCP协议

 TCP(Transmission Control Protocol 传输控制协议)

  • 传输层协议
  • 有连接
  • 可靠传输
  • 面向字节流

4.UDP协议 

UDP(User Datagram Protocol 用户数据报协议)

  • 传输层协议
  • 无连接
  • 不可靠传输
  • 面向数据报

5.网络字节序 

我们已经知道,内存中的多字节数据相对于内存地址有大端和小端之分(把一个数据的高权值位放在地址较高的地方或把一个数据的低权值位放在地址较低的地方,这就是小端,反之就是大端), 磁盘文件中的多字节数据相对于文件中的偏 移地址也有大端小端之分, 网络数据流同样有大端小端之分. 那么如何定义网络数据流的地址呢?

  • 发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出;
  • 接收主机把从网络上接到的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存;
  • 因此,网络数据流的地址应这样规定:先发出的数据是低地址,后发出的数据是高地址.
  • TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高权值字节.
  • 不管这台主机是大端机还是小端机, 都会按照这个TCP/IP规定的网络字节序来发送/接收数据;
  • 如果当前发送主机是小端, 就需要先将数据转成大端; 否则就忽略, 直接发送即可; 

 为使网络程序具有可移植性,使同样的C代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换。

#include <arpa/inet.h>

uint32_t htonl(uint32_t hostlong);

uint16_t htons(uint16_t hostshort);

uint32_t ntohl(uint32_t netlong);

uint16_t ntohs(uint16_t netshort);
  • 这些函数名很好记,h表示host,n表示network,l表示32位长整数,s表示16位短整数。
  • 例如htonl表示将32位的长整数从主机字节序转换为网络字节序,例如将IP地址转换后准备发送。
  • 如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回;
  • 如果主机是大端字节序,这些函数不做转换,将参数原封不动地返回。

二、socket编程接口

1.socket 常见API 

// 创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器)
int socket(int domain, int type, int protocol);
// 绑定端口号 (TCP/UDP, 服务器) 
int bind(int socket, const struct sockaddr *address,
 socklen_t address_len);
// 开始监听socket (TCP, 服务器)
int listen(int socket, int backlog);
// 接收请求 (TCP, 服务器)
int accept(int socket, struct sockaddr* address,
 socklen_t* address_len);
// 建立连接 (TCP, 客户端)
int connect(int sockfd, const struct sockaddr *addr,
 socklen_t addrlen);

 2.sockaddr 结构

socket API是一层抽象的网络编程接口,适用于各种底层网络协议,如IPv4、IPv6,以及后面要讲的UNIX Domain Socket. 然而, 各种网络协议的地址格式并不相同.

 套接字编程的种类

  1. 域间套接字编程 -- 在同一个机器内
  2. 原始套接字编程 -- 跳过传输层,通常用于网络工具
  3. 网络套接字编程 -- 用于用户间的网络通信

网络接口的设计者并不想设计三套接口,而是想将网络接口抽象统一化,而想统一,接口的参数必须是一样的。

  • IPv4和IPv6的地址格式定义在netinet/in.h中,IPv4地址用sockaddr_in结构体表示,包括16位地址类型, 16 位端口号和32位IP地址.
  • IPv4、IPv6地址类型分别定义为常数AF_INET、AF_INET6. 这样,只要取得某种sockaddr结构体的首地址, 不需要知道具体是哪种类型的sockaddr结构体,就可以根据地址类型字段确定结构体中的内容.
  • socket API可以都用struct sockaddr *类型表示, 在使用的时候需要强制转化成sockaddr_in; 这样的好处是程序的通用性, 可以接收IPv4, IPv6, 以及UNIX Domain Socket各种类型的sockaddr结构体指针做为参数

3.设计一个简单的UDP网络程序

netstat -nltp

查看网络连接

如何实现 整数IP和字符串IP 的相互转换?

设置一个ip结构体,每个成员都是一个一字节整数

struct ip
{
  uint8_t part1;
  uint8_t part2;
  uint8_t part3;
  uint8_t part4;
};

1.将整数转换为字符串

假如现在有一个整数IP地址, int src_ip = 123456789;

将它强转成为struct ip*类型, struct ip* p = (struct ip*)src_ip;

然后,string ip = to_string(p->part1) + "."  + to_string(p->part2) + "."  + to_string(p->part3) + "."  + to_string(p->part4);

就可以转成字符串格式了。

2.将字符串转换为整数

假如现在有个字符串IP地址, string ip = "192.168.233.148";

将它切分成 "192"  "168"  "233"  "148"

先定义一个32位整数, uint32_t IP;

取地址强转成struct ip*, struct ip* x = (struct ip*)&IP;

然后就可以

x->part1 = stoi("192");

依次类推,再强转成uint32_t类型,就可以得到一个整数IP。

但是,我们库里有相关的系统调用函数,就不需要我们手写了,我们明白其原理即可。

in_addr_t inet_addr(const char *cp);

端口号 [0~1024]基本上是系统内置的端口号,最好绑定1024以上的端口号,而1024以上的端口号有些也不能轻易绑定,比如mysql的3306端口号。

提问:客户端需要绑定socket吗?

答:要!只不过不需要用户显示的绑定!一般由OS自由随机选择!

一个端口号只能被一个进程bind,对server是如此,对client,也是如此!

client为了防止不同的应用争抢端口号发生冲突,通常是由OS分配。

client的port是多少,其实不重要,只要保证主机上的唯一性即可!

127.0.0.1:本地环回地址 ,通常用它来进行cs的测试

源码可以点击下面的地址查看

test512 · AoDong/Linux-test - 码云 - 开源中国 (gitee.com)

为我们这个Udp实现Windows做客户端,Linux做服务器的收发消息的程序

#include <iostream>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <WinSock2.h>
#include <Windows.h>

#pragma warning(disable:4996)


#pragma comment(lib, "ws2_32.lib")

const static uint16_t port = 8080;
const static std::string ip = "192.168.233.138";

int main()
{
	std::cout << "hello socket!" << std::endl;
	WSADATA wsd;
	WSAStartup(MAKEWORD(2, 2), &wsd);


    SOCKET sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        std::cout << "client create socket error" << std::endl;
        exit(1);
    }
    struct sockaddr_in server;
    //bzero(&server, sizeof(server));
    memset(&server, 0, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = inet_addr(ip.c_str());
    server.sin_port = htons(port);
    int len = sizeof(server);

    std::string message;
    char buffer[1024];
    while (true)
    {
        std::cout << "Please Enter@ ";
        std::getline(std::cin, message);

        sendto(sockfd, message.c_str(), message.size(), 0, (struct sockaddr*)&server, len);
        struct sockaddr_in tmp;
        int len1 = sizeof(tmp);
        int s = recvfrom(sockfd, buffer, 1023, 0, (struct sockaddr*)&tmp, &len1);
        if (s > 0)
        {
            buffer[s] = '\0';
            //std::cout << buffer << std::endl;
        }
    }
    closesocket(sockfd);
	WSACleanup();
	return 0;
}

4.设计一个简单的TCP网络程序

int listen(int sockfd, int backlog); //listen for connections on a socket
//accept a connection on a socket
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
initiate a connection on a socket
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
在服务器得到新连接时,单进程版服务就不太适用了,所以我们就要用到多进程,而多进程,我们的子进程就会继承两个文件描述符,ListenSock_和sockfd,我们在子进程中关不关闭ListenSock_,但是父进程强烈要求关闭sockfd。

 hao

在执行程序时,在后面加个&,表明将当前进程设置为后台进程运行。

jobs:查看后台进程。

fg 任务号:将该后台进程提至前台进程

在当前前台进程运行时,在键盘输入ctrl+z暂停,就是说像当前运行前台进程发送了一个19号信号,SIGSTOP。它会被暂停中止,并自动转为后台进程,此时bash就自动被提至前台进程。因为在命令行中,前台进程要一直存在。

bg 任务号:将暂停的后台进程恢复为前台进程

SID:进程组

打开linux,系统会创建一个bash进程,和一个session(会话),session会以bash的pid为SID创建新的进程组。

如果使进程不受用户登录或者注销的影响,就可以 -- 守护进程化。

自成进程组 自成会话的进程,守护进程

NAME
       setsid - creates a session and sets the process group ID

SYNOPSIS
       #include <sys/types.h>
       #include <unistd.h>

       pid_t setsid(void);
DESCRIPTION
       setsid()  creates a new session if the calling process is not a process group leader.  The calling process is the leader of the new session (i.e., its session ID is made the
       same as its process ID).  The calling process also becomes the process group leader of a new process group in the session (i.e., its process group ID is made the same as its
       process ID).

       The calling process will be the only process in the new process group and in the new session.

       Initially, the new session has no controlling terminal.  For details of how a session acquires a controlling terminal, see credentials(7).

注:

  • 这个进程不能是进程组的组长        

守护进程的本质 -- 孤儿进程

static const std::string nullfile = "/dev/null";

void Daemon(const std::string &cwd = "")
{
    // 1.忽略其它信号
    signal(SIGCHLD, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);
    signal(SIGSTOP, SIG_IGN);

    // 2.将自己变为独立的会话
    if(fork() > 0) exit(0);
    setsid();

    // 3.更改当前调用进程的工作目录
    if(!cwd.empty()) chdir(cwd.c_str());

    // 4.标准输入、输出和错误 重定向至/dev/null
    int fd = open(nullfile.c_str(), O_RDWR);
    if(fd >0)
    {
        dup2(fd, 0);
        dup2(fd, 1);
        dup2(fd, 2);
        close(fd);
    }
}

但是我们系统中也提供了一个这个函数 Deamon

int daemon(int nochdir, int noclose);

代码:test517 · AoDong/Linux-test - 码云 - 开源中国 (gitee.com) 

三、简单地谈一下TCP协议

TCP是全双工的,接收消息和发送消息是可以同时进行的。

TCP是一个传输控制协议

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

企业文件加密实现数据泄露防护

在数字化时代&#xff0c;数据成为企业最宝贵的资产之一。然而&#xff0c;数据泄露事件频发&#xff0c;给企业带来了巨大的经济损失和声誉风险。为了保护企业的核心利益&#xff0c;实现数据泄露防护&#xff0c;企业必须采取有效的文件加密措施。 一、数据泄露的严重性 数据…

大疆、猛犸、西圣无线麦克风哪个牌子好?大疆、西圣麦克风测评PK

在当今这个全民参与媒体创作的时代&#xff0c;视频分享已经崛起为引领流行文化的关键力量。随着自媒体领域的竞争日益白热化&#xff0c;要想在浩瀚的内容海洋中脱颖而出&#xff0c;创作出卓越的作品无疑是吸引观众目光的核心要素。然而想要成功打造这样的佳作&#xff0c;除…

目标检测——水下物体检测数据集

引言 亲爱的读者们&#xff0c;您是否在寻找某个特定的数据集&#xff0c;用于研究或项目实践&#xff1f;欢迎您在评论区留言&#xff0c;或者通过公众号私信告诉我&#xff0c;您想要的数据集的类型主题。小编会竭尽全力为您寻找&#xff0c;并在找到后第一时间与您分享。 …

[C#]使用C#部署yolov8的目标检测tensorrt模型

【测试通过环境】 win10 x64 vs2019 cuda11.7cudnn8.8.0 TensorRT-8.6.1.6 opencvsharp4.9.0 .NET Framework4.7.2 NVIDIA GeForce RTX 2070 Super 版本和上述环境版本不一样的需要重新编译TensorRtExtern.dll&#xff0c;TensorRtExtern源码地址&#xff1a;TensorRT-CShar…

Epic Pen Pro v3 解锁版安装教程 (屏幕实时标记注释工具)

前言 Epic Pen是一款功能强大的屏幕标记工具&#xff0c;允许您在屏幕上绘图或书写&#xff0c;而无需在后台与软件交互。这意味着您几乎可以注释任何东西&#xff01;使用我们流行的屏幕标记和Windows数字白板工具Epic Pen编写、绘制和突出显示&#xff0c;包括演示文稿软件&…

AlexNet神经网络训练

导包 import tensorflow as tffrom tensorflow.keras import datasets, layers, models 加载Fashion-MNIST数据集 (train_images, train_labels), (test_images, test_labels) datasets.fashion_mnist.load_data() 归一化像素值到[0, 1]区间 train_images, test_images t…

springboot vue 开源 会员收银系统 (3) 会员模块开发

前言 完整版演示 前面我们对会员系统 springboot vue 开源 会员收银系统 (2) 搭建基础框架 进行了脚手件的搭建 下面我们将从会员模块进行开发 在此之前我们先简单梳理一下会员系统的导图 可以看出会员是贯穿全部的 所以我们在此梳理一下会员表的字段 CREATE TABLE business…

决策树算法实战

本实战主要目标是讲解如何使用sklearn库来构造决策树&#xff0c;包括其中的一些参数的使用&#xff0c;以及参数调优对模型精确度的影响。 1. 数据处理 导入Pandas和Matplotlib两个库。 # 导入Pandas和Matplotlib两个库 %matplotlib inline import matplotlib.pyplot as pl…

buuctf_RE

[WMCTF2020]easy_re 简单输入flag 但是下断点后&#xff0c;还没走几步就报错退出了。 确实没有打印的字符串 main函数也看不懂在干嘛 int __cdecl main(int argc, const char **argv, const char **envp) {__int64 v4; // r13char v5; // r12__int64 v6; // rax_QWORD *v7;…

english语法

从句&#xff1a;简单句连词 介词

maven部署到私服

方法一:网页上传 1、账号登录 用户名/密码 2、地址 http://自己的ip:自己的端口/nexus 3、查看Repositories列表&#xff0c;选择Public Repositories&#xff0c;确定待上传jar包不在私服中 4、选择3rd party仓库&#xff0c;点击Artifact Upload页签 5、GAV Definition选…

Aria2下载安装使用

这里写目录标题 下载Aria2 配置创建 aria2.conf 文件创建 aria2.session 文件 Aria2的使用基础使用多源下载多线程下载后台下载配置文件启动 AriaNg下载安装AriaNg配置AriaNg使用 Tracker 列表 aria2 是一款免费开源跨平台且不限速的多线程下载软件&#xff0c;其优点是速度快、…

安全阀检测周期:确定因素与操作流程详解

在工业生产中&#xff0c;安全阀扮演着至关重要的角色&#xff0c;其性能的稳定性和准确性直接关系到设备和系统的安全。为确保安全阀的正常运行和事故防范&#xff0c;对其进行定期检测显得尤为关键。 接下来&#xff0c;佰德将深入探讨安全阀检测周期相关的内容&#xff0c;…

前端 CSS 经典:多行文本擦除效果

前言&#xff1a;使用动画实现更改变量 --p&#xff0c;实现多行文本擦除效果&#xff0c;css 动画逻辑&#xff0c;什么样的动画是生效的&#xff0c;一定是一个数值类的 CSS 属性。--p 只是个变量&#xff0c;不是 CSS 属性&#xff0c;通过 Houdini API 使它变成一个属性。 …

后量子加密算法的数学原理

后量子加密算法是一类专为抵御量子计算机攻击而设计的加密算法。随着量子计算技术的迅速发展&#xff0c;传统的加密算法如RSA和椭圆曲线密码学在量子计算机面前变得脆弱&#xff0c;因此&#xff0c;开发能够在量子计算时代保持安全性的加密算法变得尤为重要。下面将详细介绍后…

【kubernetes】关于k8s集群如何将pod调度到指定node节点(亲和与反亲和等)

目录 一、调度约束 1.1K8S的 List-Watch 机制 ⭐⭐⭐⭐⭐ 1.1.1Pod 启动典型创建过程 二、调度过程 2.1Predicate&#xff08;预选策略&#xff09; 常见的算法 2.2priorities&#xff08;优选策略&#xff09;常见的算法 三、k8s将pod调度到指定node的方法 3.1指定…

【ARM+Codesys案例】基于全志T3+Codesys软PLC的3C点胶边缘控制解决方案:整合了运动控制、视觉、激光测高等技术

视觉精密点胶控制方案 针对直交型机构的平面点涂胶应用&#xff0c;基于CODESYS软件平台开发的一站式PC型控制器解决方案&#xff0c;包含运动控制器硬件和点胶应用软件。方案整合了运动控制、视觉、激光测高等技术&#xff0c;高效精密的控制胶水点涂于产品表面或内部&#x…

Linux查看设备信息命令

dmidecode | grep Product Name 查看grub版本号&#xff1a;rpm -qa | grep -i "grub" 客户端操作系统版本&#xff1a; cat /etc/issue cat /etc/redhat-release 处理器品牌及型号&#xff1a; less /proc/cpuinfo |grep model

瓦罗兰特国际服怎么注册账号 瓦罗兰特 无畏契约账号注册教程

瓦罗兰特国际服怎么注册账号 瓦罗兰特 无畏契约账号注册教程 瓦罗兰特作为拳头游戏开发的一款多人竞技第一人称射击游戏&#xff0c;自从2020年发布之后&#xff0c;热度持续升高&#xff0c;游戏采用5V5竞技模式&#xff0c;采用了传统FPS中游戏的类型&#xff0c;玩家们分为…

WorldSpace下的合批策略与ScreenSpace有什么区别

1&#xff09;WorldSpace下的合批策略与ScreenSpace有什么区别 2&#xff09;在iOS上用Metal取代OpenGL的多么 3&#xff09;在动画蓝图中将两个或多个动画同时融合到同一个网格 4&#xff09;Mipmap如何限定层级 这是第387篇UWA技术知识分享的推送&#xff0c;精选了UWA社区的…