Linux下进程间通信

这篇具有很好参考价值的文章主要介绍了Linux下进程间通信。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

进程间通信的目的

数据传输: 一个进程需要将它自己的数据发送给其它进程;
资源共享: 多个进程间共享同一份资源;
通知事件: 一个进程需要像另一个或者另一组进程发送某个消息,通知它们发生了什么事;(比如:进程终止时要通知父进程);
进程控制: 有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变;

进程间通信的手段的分类

管道:

  1. 匿名管道;
  2. 有名管道;

System V IPC:

  1. System V 消息队列;
  2. System V 共享内存;
  3. System V 信号量;

POSIX IPC:

  1. POSIX 消息队列;
  2. POSIX 共享内存;
  3. POSIX 信号量;

管道

什么是管道

管道是Unix最古老的进程间通信的手段;
我们把从一个进程连接到另一个进程的一个数据流称为一个管道;

管道原理

根据我们之前学的知识我们可以知道,任何两个进程之间都是相互独立的,我们当前进程无法直接访问另一个进程的数据!
可是,如果我们两个进程都看向同一份资源呢?
比如:A进程看到了一个log.txt文件,进程B也看到了log.txt文件;
那么如果现在A进程是对log.txt文件进行写入操作,而我们的进程B是对log.txt文件进行读取操作,那么是不是对于我B进程来说是不是就拿到了A进程发送出来的数据?
你看我们不就通过这样的一种方式,让两个相互独立的进程就"交流"起来了嘛!
现在我们在对这个log.txt文件稍加修饰:比如:我现在只允许A进程向log.txt文件进行写入操作,不允许进行读取,同时我们规定B文件只能向log.txt文件进行读取操作,不允许进行写,那么你看A进程到B进程的数据流动是不是就有画面感了,数据只允许从A进程流向B进程;
我们把log.txt这种< “只允许单向数据流动的、充当"中间人"的文件”就称作" >管道文件"!
这就是"管道文件"的原理!
Linux下进程间通信
同时通过管道原理的讲解,我们也揭示了进程间通信的本质:就是让不同的进程看到同一份资源!

管道文件分为两种:匿名管道文件、有名管道文件
一般情况下,如果我们只说管道文件的话,一般都是指的匿名管道文件;

匿名管道

人如其名,这个管道文件就是没有名字,同时这个管道文件不是一个磁盘文件,它是一个由OS维护的内存级别的文件,就是说该文件的文件内容和属性并不存储于磁盘上,这些数据就在内存中;
1、既然我任意两个进程之间都能通过匿名管道来进行通信,那么是不是说在内存中可能会同时存在大量的匿名管道文件?
是的!因为在内存中可不止我们这A、B两个进程需要进程进行通信,也有可能C进程与D进程也需要进行通信,他们也有可能采用匿名管道的方式,那么就势必会造成内存中会存在大量的匿名管道文件!
2、那么OS要不要把这些匿名管道文件管理起来呢?
答案:OS作为计算机中的管理者,自然是需要帮助我们把这些匿名管道文件管理起来!为进程提供良好的运行环境;
3、OS如何管理这些匿名管道文件呢?
答案:先描述,再组织! Linux下一切皆文件,匿名管道文件也不例外,OS会用struct file的结构体来描述一个匿名管道文件,这不过这个struct file这个结构体OS是不会为其分配缓冲区的,因为这是个内存级别的文件,不需要将数据刷盘到磁盘,因此匿名管道文件的struct file操作系统不会为其分配缓冲区,除此之外它与那些磁盘文件别无差异!既然都用struct file描述起来了,那么我们只要找到struct file结构体,我们就能找到struct file结构体对应的匿名管道文件!同时OS可能会利用某种数据结构比如(链表、数组等)把这些struct file结构体组织起来,之后OS对于这些匿名管道文件的管理,就变成的对于链表的增删查改!至此OS就完成了对于匿名管道文件的管理!

4、现在问题又来了,既然是匿名管道文件,那么我们如何使用这个这个匿名管道文件呢?
就比如:现在我A进程创建并打开了一个匿名管道文件,我A进程就能拿到匿名文件在我这个进程中的文件描述符,A进程再通过文件描述符来找到匿名管道文件,这没问题!可是我B进程如何打开这个匿名管道文件呢?A进程既然已经创建好了匿名管道文件,那么就自然等待着我们B进程来打开它啊,然后进行欢快的交流,可是这个文件是匿名的、还是内存级别的,我B进程如何利用系统调用open()来打开这个文件啊?我B进程连打开那个匿名文件都不知道,我如何如A进程进行通信?
因此,我们第一步要解决A、B进程如何看到同一份匿名管道文件的问题?
匿名管道文件,没有名字我们不好打开,可是作为创建者A是可以打开的并且准确知道该匿名管道文件的文件描述符的,如果我B进程是A进程的子进程呢?我B进程是不是就会继承父(A)进程的大部分属性,包括文件描述符表:
Linux下进程间通信
这样做到话,A、B两个进程就看到了同一份管道文件资源,就可以进行快乐的通信了!
细心的读者可以发现我们A进程在打开管道文件是分别用的两次不同的方式来打开的:第一次用只写、第二次用只读;
为什么要这样?
我直接利用只读的形式一次打开它不香吗?
我么前面说了,管道文件的数据流动是单向的,如果我们以读写的方式打开匿名管道文件,那么子进程继承下去过后也是以读写的方式打开的匿名管道文件,无法保证数据流动的单向性!因此我们不能用读写的方式来一次性到位!
那为什么分两次就行了呢?
很简单,如果我们想要A进程进行发送数据,B进程进行读取数据,那么在B进程继承A进程过后,马上关闭A进程的读描述符,再马上关闭B进程的写文件描述符,那么这样,A进程就只能对匿名管道文件进程写操作,B进程也就只能对匿名管道文件进行读操作了这样也就保证了数据再管道文件中的单向流动性!(我们也可以让B进行进行写,A进程进行读,只需关闭对应的进程的文件描述就可以了!)

Linux下进程间通信

创建匿名管道文件

话不多说,我们先创建一个匿名管道出来玩一玩:

#include <unistd.h>
int pipe(int pipefd[2]);//调用这个系统调用的进程来创建匿名管道
返回值: 创建成功,返回0;创建失败返回-1;
参数: 输出型参数,就是用于存储管道文件在调用pipe函数的进程中的文件描述符;
pipefd[0]:用于存储管道文件的读端;pipefd[1]:用于存储管道文件的写端;
Linux下进程间通信
根据上面使用匿名管道的原理,父进程有了,父进程也创建了管道文件,那么就开始创建子进程了,让子进程能继承父进程的文件描述符表,然后父子进程就能看见同一份匿名管道资源,但是我们现在让父进程专门执行写,子进程就专门进行读,因此我们需要关闭父进程的pipefd[0]号文件描述符,关闭子进程的pipefd[1]号文件描述符:

#include<iostream>
#include<unistd.h>
#include<cerrno>
#include<cstring>
int main()
{
    int pipefd[2];
        int n=pipe(pipefd);
        if(n!=0)
        {
            //管道文件创建是败
            std::cerr<<"error num:"<<errno<<"error message:"<<strerror(errno)<<std::endl;
            exit(1);
        }
        int id=fork();
        if(id==0)
        {
            //child
            //关闭子进程对于管道文件的写端
            close(pipefd[1]);
            
            //通信……

            close(pipefd[0]);//子进程通信完毕,退出前关闭打开的文件;
            exit(0);
        }
        //father
        close(pipefd[0]);//关闭父进程对于管道文件的读端
       
        //通信……

        close(pipefd[1]);//通信完毕,关闭父进程打开的文件
    return 0;
}

至此,两个独立的进程就可以开始进行通信了;
为了,更加清晰的看到,两个进程之间确实在进行通信,我们可以写一些,简单的测试用语:

#include<iostream>
#include<unistd.h>
#include<cerrno>
#include<cstring>
#include<cstdio>
#include<cstdlib>
int main()
{
    int pipefd[2];
        int n=pipe(pipefd);
        if(n!=0)
        {
            //管道文件创建是败
            std::cerr<<"error num:"<<errno<<"error message:"<<strerror(errno)<<std::endl;
            exit(1);
        }
        int id=fork();
        if(id==0)
        {
            //child
            //关闭子进程对于管道文件的写端
            close(pipefd[1]);
            //通信……
            while (true)
            {
                char buff[1024]={0};
                int n=read(pipefd[0],buff,sizeof(buff)-1);
                printf("我是子进程,我的pid是%d.  父进程=>子进程信息:%s\n",getpid(),buff);
            }
            close(pipefd[0]);//子进程通信完毕,退出前关闭打开的文件;
            exit(0);
        }
        //father
       // close(pipefd[0]);//关闭父进程对于管道文件的读端
        //通信……
        while(true)
        {
            char buff[1024];
            snprintf(buff,sizeof(buff),"你好子进程,我是父进程.我的pid是%d,子进程的pid是%d\n",getpid(),id);
            write(pipefd[1],buff,strlen(buff));//将信息写入管道文件中
            sleep(1);
        }

        close(pipefd[1]);//通信完毕,关闭父进程打开的文件
    return 0;
}

Linux下进程间通信
子进程接收到的信息;

匿名管道的特点

1、管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道
2、匿名管道文件的本质就是文件,同时匿名管道文件的生命周期随着进程;
3、管道通信,通常用来进行具有“血缘关系”的进程间进行通信,比如:父子进程、兄弟进程、爷孙进程等;
4、在管道通信中,写入的次数和读取的次数,不是严格匹配的,读写次数的多少没有强相关;
5、具有一定的协同能力,让read和write能够按照一定的步骤进行通信,自带同步机制;

匿名管道的4种场景

1、如果我们read完管道里面的数据,对方又不发了,我们(read端)就只能等待:
Linux下进程间通信
Linux下进程间通信
实际上是子进程卡在了read的内部,我们可以用实验证明一下:
Linux下进程间通信实验结果:
Linux下进程间通信
2、如果读端一直不读数据,写端一直写数据,那么当管道文件写满过后,写端则不在写数据,写端会卡在write函数内部;
Linux下进程间通信
实验结果:
Linux下进程间通信
3、当我们关闭了写端,我们又读取完毕了管道内的所有数据,然后read在读,read会读到文件末尾,然后返回0;这也很好理解:我们读端在读的时候发现,写端都被关闭了,那么就再也不会有进程向管道里面写入数据了,就不会再报希望的去等待写端进行写了,而是直接返回0,表示读到了文件末尾;
4、当我们读端关闭了,那么OS将给写端进程发一个13号信号,来终止掉写端进程;

有名管道

管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信。
如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道。
命名管道是一种特殊类型的文件

有名管道的创建

命令行上创建一个有名管道文件:
mkfifo filename
Linux下进程间通信
有名管道文件的文件属性是存储在磁盘上的,因此,有名管道文件是具有inode编号的,但是有名管道的文件内容与匿名管道一样是存储在内存中的,这块内存有OS来维护;

当然除了利用命令来创建有名管道文件,我们也可以利用函数在代码中创建:
int mkfifo(const char *filename,mode_t mode);
参数: filename:有名管道的文件名
mode:有名管道文件的的权限,受umask掩码约束
返回值: 成功返回0,失败返回-1;
有名管道只用创建一次就行了;

eg:

//读端进程
#include<iostream>
#include<sys/types.h>
#include<sys/stat.h>
#include<cstring>
#include<fcntl.h>
#include<unistd.h>
int main()
{
    //test1.cc进程创建有名管道
    int n=mkfifo("fifo",0666);//创建有名管道,并且设置有名管道文件的权限是0666,由于受umask码限制,最终fifo文件权限为0664
    if(n==-1)
    {
        //管道文件创建是败
        std::cerr<<"error num:"<<errno<<"error message:"<<strerror(errno)<<std::endl;
        exit(1);
    }
    //打开有名管道文件
    int fd=open("fifo",O_RDONLY);
    //开始通信
    while(true)
    {
        char buff[1024];
        int n=read(fd,buff,sizeof(buff)-1);
        if(n>0)
        buff[n]=0;
        printf("我是test1.cc,test2.cc给我的信息是%s\n",buff);
    }
    close(fd);
    return 0;
}
///
//写端进程
#include<iostream>
#include<sys/types.h>
#include<sys/stat.h>
#include<cstring>
#include<fcntl.h>
#include<unistd.h>
int main()
{
    //test2.cc以写的方式打开有名管道文件
    int fd=open("fifo",O_WRONLY);
    //开始通信
    while(true)
    {
        char buff[1024];
        sprintf(buff,"你好test1.cc,我是test2.cc\n");
        write(fd,buff,strlen(buff));
        sleep(1);
    }
    close(fd);
    return 0;
}

有名管道总结

1、如果我们要创建的有名管道文件已经存在时,我们的mkfifo函数会创建失败:
2、匿名管道的4种场景,同样适用于有名管道
3、有名管道,不仅可以作用与“血缘进程”之间,也可用用于非血缘进程之间;
4、匿名管道,再利用pipe创建的时候就已经帮助我们打开了,不需后续的手动打开;但是对于有名管道来说,我们在利用mkfifo创建有名管道过后,还需要利用open系统调用手动打开;
5、我们在使用完有名管道后,每次都需要手动删除有名管道文件,很是麻烦,我们可以在代码中加入unlink(filename)系统调用,来自动删除有名管道文件,只要程序已结束,有名管道文件就会被自动删除。

命名管道的打开规则

如果当前打开操作是为读而打开FIFO时
O_NONBLOCK disable:阻塞直到有相应进程为写而打开该FIFO
O_NONBLOCK enable:立刻返回成功
如果当前打开操作是为写而打开FIFO时
O_NONBLOCK disable:阻塞直到有相应进程为读而打开该FIFO
O_NONBLOCK enable:立刻返回失败,错误码为ENXIO

system V 共享内存

共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据;

共享内存原理

我们都知道,进程间通信的本质就是让两个互相独立的进程看到同一份资源,那如果两个进程看到的是同一份物理内存呢?那么两个进程之间是不是也能相互进行通信?
我们都知道,每个进程都有属于自己的进程地址空间表和页表,进程所使直接使用的内存地址,实际就是进程地址空间上的虚拟地址,最终还是要通过页表来映射到对应的物理内存上去的;
那么现在如果有两个进程A、B;
A进程映射到物理内存m1,那么B进程是不是也可以映射到物理内存m1呢?
答案是毋庸置疑的!当然可以!
Linux下进程间通信
你看这样我们不就让两个互无关系的两个进程可以进行通信了,因为A、B两个进程都看到了m1这块物理内存,我们把m1这块内存叫做 “共享内存” ;

建立通信

创建共享内存:
int shmget(key_t key, size_t size, int shmflg);
参数:
key: 共享内存的标识符,可由我们用户自己设置,但是要保证其唯一性,不能与之前设置的共享内存的key值冲突;因此我们通常使用 key_t ftok(const char *pathname, int proj_id) 函数来生成key值;
设置这个标识符的原因:就是为了方便后续进程容易看到同一份共享内存;毕竟共享内存不比有名管道,有名字,可以通过名字去查找,共享内存没有名字,后续的进程无法通过名字去查找共享内存,因此我们在利用共享内存进行通信之前必须做出约定,我们准备用那一块共享内存进行通信,而这个key值就是标识共享内存的标识符,相当于共享内存的ID;
size: 需要创建的共享内存的大小,字节为单位;
shmflag: 以何种方式创建共享内促;是位图的一种形式;
常见的选项有:
SHM_CREAT: 创建一个标识符为key的共享内存;如果已经存在一个标识符为key的共享内存,则返回这个共享内存;如果不存在一个标识符为key的共享内存,则创建之,并将其标识符设置为key值,然后返回这个新创建的共享内存;
SHM_CREAT|SHM_EXCL: SHM_EXCL不能单独使用,只能配合着SHM_CREAT来使用;这个组合"键"的意思是:创建一个共享内存,如果已经存在一个标识符为key的共享内存,则直接报错!
如果不存在一个标识符为key的共享内存,则创建之,并将其标识符设置为key值,然后返回这个新创建的共享内存;这也就保证了,如果我们得到了一个共享内存,那么这个共享内存一定是新创建的!
当然,在设置shmflag的时候,我们也可以给共享内存设置权限,因为Linux下一切皆文件!这里设置的权限不受umask掩码的约束;
eg:SHM_CREAT|0666//将共享内存的设置权限为0666
返回值: 如果创建失败,则返回-1;如果成功一个共享内存描述符被返回;
这个共享内存描述符与key是差不多的,都是用来区别不同的共享内存的;如果要说它与key的关系的话,我们可以这样看待:key值就类比于文件系统中的inode编号;shmget返回值就类似于open()函数的返回值(文件描述符);共享内存描述符一样是在上层给用户使用的,而key值是在OS层给OS识别不同共享内存的标识符;

建立映射:
上面的shmget()只是在物理内存中帮我们申请好了一块物理内存罢了,我们这时候还不能直接使用这块物理内存,因为这块物理内存还没有经过进程的页表的映射,映射到进程的地址空间上去:
Linux下进程间通信
因此我们需要shmat()来帮助我们完成,共享内存与进程之间的映射
void *shmat(int shmid, const void *shmaddr, int shmflg);
参数:
shmid: 共享内存描述符,也就是shmget的返回值;告诉shmat需要处理的共享内存是哪个;
shmaddr:用于指定共享内存映射到那个虚拟地址处,一般我们不这么干,我们通常把这个参数设置为nullptr,交给OS自己去决定应该将共享内存映射到那一块虚拟空间;
shmflg: 告诉shmat,它应该以什么样的方式对将共享内存映射到我们的进程地址空间上;也是个位图;
常设置为0:表示将共享内存以读写的方式映射到当前进程上;
SHM_RDONLY:表示以只读的方式映射到当前进程上;
这里设置的映射方式,与我们之前在shmget处为共享内存设置的权限有很大的关系,如果我们刚开始设置的权限中就没有放开写权限,那么我们是不能用shmflg=0的方式来映射到当前进程的,OS会提示我们Permission denied,我们就只能用SHM_RDONLY的方式来建立映射,因为我们设置的共享内存权限中根本没有放开写权限,怎么能谈在以写的方式来链接,这时的共享内存本身就不支持!
返回值: 成功,返回共享内存映射到当前进程地址空间中的虚拟地址;这时的虚拟地址与我们平常代码中的char *之类的地址,并无差异,可以直接使用!失败返回(void *)-1

回收共享内存

取消映射:
既然共享内存创建好了,与进程的映射也建立,那么不同的进程之间,就能愉快的进行通信了;
可是通信完毕过后呢?
我们是不是要回收共享内存?
共享内存可不同管道文件那样,生命周期随进程,进程退出,就销毁;相反,共享内存的生命周期随OS,只要我们不关机,不自己主动去销毁共享内存,那么共享内存就会一直存在!进程退出也会一直存在!
因此在通信结束过后,我们需要主动去销毁共享内存;
共享内存的销毁主要分两步:
1、取消进程与共享内存的映射关系,就是shmat的反操作;
2、当进程与共享内存的链接数为0时,OS就会真正的销毁共享内存!
我们这一步,先讨论取消进程与共享内存的链接:
int shmdt(const void *shmaddr);
参数:

shmaddr:需要取消链接的共享内存在当前进程地址空间中的虚拟地址
返回值:
取消成功,返回0;取消失败,返回-1;

销毁共享内存:
进程与共享内存的链接取消了,接下来就需要销毁了,销毁与创建一样都只需要进行一次即可;
谁创建的共享内存,谁销毁的原则;
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
参数:
shmid:销毁的共享内存
cmd:用于确定shmctl的工作性质;
常见:IPC_RMID:表示shmctl()的工作是销毁共享内存,这里销毁只有当共享内存的链接进程数为0了,才会真正的被销毁,否则,则在描述共享内存的结构体中的shm_perm模式字段的(非标准)SHM_DEST标志将设置IPC_STAT检索的关联数据结构。也就是说共享内存不会被真正的回收,只是会被打上"已死亡"的标签!;
IPC_STAT:那么此时shmctl的工作是获取共享内存的属性信息,这里的属性信息受权限约束!通常将配合第三个参数使用,将获取到的信息放入buf所指的结构体中;
buf:通常配合的IPC_STAT使用,输出型参数,用于存放获取到的共享内存的结构信息;
如果是IPC_RMID模式的话,shmctl的工作是销毁共享内存,不必获取共享内存的状态,buf直接给nullptr就好了;
返回值:成功,返回0;失败返回-1;

开始通信

我们可以写一个简单的demo,来表示两个进程之间通过共享内存来进行通信:

//头文件
#include<iostream>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/types.h>
#include<unistd.h>
#include<cstring>

#ifndef __HAHAHA___
#define __HAHAHA___

#define PATH_NAME "."//确定ftok的第一个参数
#define PROJ_ID 1234 //确定ftok的第二个参数,这两个参数自己随便设置,只要合法就行
#define SHM_SIZE 1024//确定共享内存的大小

#endif
//Master进程进行写
#include"Comm.hpp"
int main()
{
    //创建key值
    key_t key=ftok(PATH_NAME,PROJ_ID);
    //创建共享内存,保证获得的共享内存是新建的
    int shmid=shmget(key,SHM_SIZE,IPC_CREAT|IPC_EXCL|0666);
    //建立映射
    void*begin=shmat(shmid,nullptr,0);
    //开始进行通信
    char *buff=(char*)begin;
    int  cnt=0;
    sleep(2);
    while(cnt<26)
    {
        //直接向共享内存写入数据
        buff[cnt]='A'+cnt;
        buff[++cnt]=0;
        sleep(1);
    }
    //取消链接
    shmdt(begin);
    //销毁共享内存
    shmctl(shmid,IPC_RMID,nullptr);
    return 0;
}
/

//Servant进程进行读
#include"Comm.hpp"
int main()
{
    //创建key值
    key_t key=ftok(PATH_NAME,PROJ_ID);
    //获取共享内存,Master进程已经创建好了,Servant进程只管获取就行了
    int shmid=shmget(key,SHM_SIZE,IPC_CREAT);
    //建立映射
    void*begin=shmat(shmid,nullptr,0);
    //开始进行通信
    char *buff=(char*)begin;
    while(true)
    {
        std::cout<<"I am Servant,MAster give me message is:"<<buff<<std::endl;
        if(strlen(buff)==26)
        break;
        sleep(1);
    }
    //取消链接
    shmdt(begin);
    return 0;
}

//注意运行时机,先运行Master进程,在运行Servant进程
通信效果:
Linux下进程间通信

命令操作共享内存

我们可以利用命令查看我们创建的共享内存:
ipcs -m
查看当前OS下的所有共享内存:
Linux下进程间通信
-q:查看当前OS下的所有消息队列;
-s:查看当前OS下的所有信号量;
不带选项,将一起展示(消息队列、共享内存、信号量);

删除我们创建的共享内存:
ipcrm -m shmid
Linux下进程间通信
ipcrm -s semid:删除信号量;
ipcrm -q mspid:删除消息队列
ipcrm -a 删除所有ipc资源[共享内存|消息队列|信号量]

共享内存与管道的区别

共享内存区是最快的IPC形式:
解释如图:
Linux下进程间通信
通过对比,我们可以知道,很明细使用共享内存来进行通信,要远比使用管道来通信的效率更高!
因为:我们使用共享内存通信,只需要1次copy,而使用管道通信,至少要使用3次copy;copy是很花时间的,很明显使用管道通信的效率更高!文章来源地址https://www.toymoban.com/news/detail-446065.html

到了这里,关于Linux下进程间通信的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 计算机网络-数据通信基础知识(数据通信模型 相关术语 单工/半双工/全双工 串行/并行 同步/异步 码元 数据传输速率 带宽)

    广域网中有模拟信道,模拟信道能传模拟信号,不能传数字信号 数据从计算机网卡中以数字信号发出,经过调制解调器转换为模拟信号以放到广域网上的模拟信道传输,再由调制解调器转换为数字信号,数字信号经过计算机的转换才将数据展现出来 发送端的调制解调器:发

    2024年01月25日
    浏览(43)
  • 前端(二十一)——WebSocket:实现实时双向数据传输的Web通信协议

    🤨博主:小猫娃来啦 🤨文章核心: WebSocket:实现实时双向数据传输的Web通信协议 在当今互联网时代,实时通信已成为很多应用的需求。为了满足这种需求,WebSocket协议被设计出来。WebSocket是一种基于TCP议的全双工通信协议,通过WebSocket,Web应用程序可以与服务器建立持久

    2024年02月04日
    浏览(56)
  • 三、计算机理论-计算机网络-物理层,数据通信的理论基础,物理传输媒体、编码与传输技术及传输系统

    物理层概述 物理层为数据链路层提供了一条在物理的传输媒体上传送和接受比特流的能力。物理层提供信道的物理连接,主要任务可以描述为确定与传输媒体的接口有关的一些特性:机械特性、电气特性、功能特性、过程特性 数据通信的理论基础 数据通信的意义 主要是指用

    2024年01月22日
    浏览(55)
  • 通信协议详解(二):IIC总线协议(传输时序+数据格式+设计实现)

        IIC(Inter-Integrated Circuit)是一种具有两线传输的串行通信总线,使用多主从架构,由飞利浦公司在1980年为了让主板、嵌入式系统或手机连接低速周边设备而提出,适用于数据量不大且传输距离短的场合。     IIC串行总线由两根信号线组成,一根是双向的 数据线

    2024年02月04日
    浏览(45)
  • 详解TCP/IP协议第三篇:通信数据在OSI通信模型的上下传输

    😉😉 学习交流群: ✅✅1:这是孙哥suns给大家的福利! ✨✨2:我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料 🥭🥭3:QQ群:583783824   📚📚  工作微信:BigTreeJava 拉你进微信群,免费领取! 🍎🍎4:本文章内容出自上述:Spring应用课程!💞💞

    2024年02月09日
    浏览(34)
  • 通信模型四层(TCP/IP)、五层、七层(OSI)的作用、协议及数据传输单位

    四层模型 五层模型 七层模型 每层作用 物理层:传输比特流 数据链路层:控制网络层和物理层之间的通信 网络层:IP寻址和路由选择 传输层:建立、维护、管理端到端连接 会话层:建立、维护、管理会话连接 表示层:数据格式化,加密、解密、 应用层:为应用程序提供网

    2024年02月03日
    浏览(36)
  • 远程服务和web服务和前端,三方通过socket和websocket进行双向通信传输数据

    1. 什么是socket? 在计算机通信领域,socket 被翻译为“套接字”,它是计算机之间进行通信的一种约定或一种方式。通过 socket 这种约定,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据。 2. 什么是websocket? WebSocket是一种网络通信协议,是HTML5新增的特性,

    2024年02月15日
    浏览(45)
  • Linux 传输数据(Linux和windows)

    1.使用 xftp 可以传输 2.使用 lrzsz 传输 首先下载: apt-get install lrzsz yum install lrzsz -y 以当前 终端(xshell) 所在的系统为准: 1.从 其他 windows 中 传输数据到 本地系统: cd 到要保存文件的位置 输入指令:rz 2.将文件上传其他系统: 输入命令:sz [文件名] 1.把当前 linux 的文件 传

    2024年02月13日
    浏览(28)
  • Unity使用webSocket与服务器通信(三)——C#服务端(Fleck)与Unity客户端( NativeWebSocket)传输多种数据数据

    1、字符串数据 简单的字符串:比如登录请求信息,登录结果返回的信息。 用json系列化的字符串:比如上传一个表到服务器,让它写入到数据库中。 读取文件的时候,读取的是string内容。 2、二进制数据 比如传输的是文件:例如myword.doc,myexcel.xls或者是assetboundle文件。 比如

    2023年04月08日
    浏览(35)
  • Linux如何传输数据至另一台Linux?

    Windows之间互相传输数据属常见和普及的日常操作, 相信大家也不会陌生及懂操作, 但Linux如何传输数据至另一台Linux呢? 文章内会详细为大家解说 一般资料传输是指数据拷贝到另一台机的行为叫资料传输,一向使用Windows的朋友,可能会认为资料传输就是简单的复制及贴上, 但

    2023年04月16日
    浏览(25)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包