项目(三)

1、客户端开发流程

  1. 创建socket,得到一个通信的文件描述符
  2. 绑定------不是必须的(内核随机分配)
  3. connect服务端:在给IP和端口赋值时需要注意主机字节序和网络字节序的转换
  4. 循环收发数据:读或者写都是操作内核的缓冲区,并不负责发送或者接收数据,发送或者接受是由内核负责的
  5. 关闭文件描述符close

2、服务端开发流程

  1. 创建socket,创建监听描述符
  2. 设置端口复用
  3. 绑定----必须的:ip加端口号可以确定唯一一个服务
  4. 监听listen
  5. 接受新连接accept
  6. 循环收发数据
  7. 关闭套接字

3、同步和异步:异步效率比同步高

同步:例如,客户端发送数据给服务端,发送完成后,就read阻塞等待数据,读数据不完成则不完成后续操作

异步:客户端发送数据给服务端,发送完成后,没有等待read数据,而是直接处理后续操作

4、阻塞和非阻塞

阻塞:比如accept和read都是阻塞函数,条件不满足,就一直阻塞等待

5、同步非阻塞、同步阻塞、异步阻塞和异步非阻塞

异步阻塞:select\epoll\poll

6、长连接和短链接

长连接:通常用于通信双方数据交换频繁的情况

-------心跳包

短链接:通常用于通信双方交换数据完成后就断开连接

同步短链接:

异步长连接:

7、网络知识回顾

  1. 一个文件描述符对应两个内核文件缓冲区
  2. 三次握手、四次挥手、滑动窗口:主要进行流量控制
  3. TCP状态转化图
  4. 多进程、多线程
  5. epoll反应堆
  6. 线程池

8、通信效率:单位时间客户端/服务端接受/发送数据的量

客户端通信效率分析:

  1. 单进程,只处理一个链接
  2. 多线程使用同一个链接
  3. 多线程使用多个连接
  4. 连接池+线程池:连接池不能用于服务端,链接只有客户端发起请求之后才有,只有客户端可以用 :

连接池:

  1. 有一个数据结构保存链接
  2. 创建连接池操作----poolInit()
  3. 获取链接的操作
  4. 将连接放回的操作
  5. 动态调整连接池的数量
  6. 销毁连接池

9、客户端类设计思想

10、服务端设计思想

11、进程间通信回顾

  1. 管道pipe
     #include <unistd.h>
    
     int pipe(int pipefd[2]);
    

    特点:1、只能用于有血缘关系的进程间通信 2、管道有两端,管道数据流向由管道的写端到管道的读端 3、管道的本质时一个内核缓冲区 4、数据从管道中读走以后就不存在了 5、管道的实现实际上是环形队列 6、默认下管道的读写端都是阻塞的 

  2. 命名管道:fifo  特点:1、既可以用于有血缘关系的进程间通信,也可以用于无血缘关系的通信 2、创建的fifo文件大小为0,是linux文件7种之一 3、使用fifo需要先创建fifo文件 4、使用fifo完成通信两个进程必须打开相同的FIFO文件 5、效率比pipe低

     #include <sys/types.h>
     #include <sys/stat.h>
    
     int mkfifo(const char *pathname, mode_t mode);
    
  3. mmap:共享映射区,本质是将文件内容映射到内存

     #include <sys/mman.h>
    
     void *mmap(void *addr, size_t length, int prot, int flags,
                      int fd, off_t offset);
    

    特点:1、有无血缘关系都可以使用 2、如果完成没有血缘关系的必须使用文件 3、若使用MAP_SHARED,对内存的修改会反映到文件中 4、需要注意mmap存在调用失败的情况 5、匿名映射只能用于有血缘关系的进程间

  4. 信号:进程A给进程B发送信号,本质上是进程A给内核发送信号然后内核给B发送信号

     #include <sys/types.h>
     #include <signal.h>
    
       int kill(pid_t pid, int sig);
    相关函数:
    signal
    kill
    sigaction
    abort
    raise
    alarm|setitmer
    sigemptyset sigaddset sigfillset sigdelset  sigismember sigpromask sigpending 
    SIGINT SIGQUIT SIGALRM SIGTERM SIGKILL SIGSTOP SIGUSR1 SIGUSR2 SIGPIPE 
    SIGCHILD信号

    特点:1、信号不能携带大量信息 2、信号优先级比较高,会打断程序执行 3、不建议使用信号完成进程间通信 4、一般使用kill命令给一个进程发送信号,进程收到信号之后调用信号处理函数  信号处理动作:1、忽略信号 2、执行默认处理动作 3、执行用户自定义函数

  5. 本地socket

    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netinet/tcp.h>
    
    tcp_socket = socket(AF_UNIX, type, 0);
    tcp/udp都可以

    1、如果使用tcp通信,bind时需要指定一个文件,若文件存在会报错,unlink删除 2、独活写其实都是通过文件描述符去操作内核缓冲区 3、编写流程可以直接参考tcp/udp开发流程

  6. 共享内存:实质是将内核的一块内存映射到进程中的内存,操作本地内存就相当于操作共享内存(key值区分)

使用共享内存步骤:

  1. 创建共享内存
  2. 关联共享内存
  3. 使用共享内存-----读写共享内存
  4. 断开与共享内存的关联
  5. 删除共享内存

创建共享内存:

 #include <sys/ipc.h>
 #include <sys/shm.h>

 int shmget(key_t key, size_t size, int shmflg);

创建或者获得共享内存ID

参数:key:是一个无符号整型值,唯一标识一份共享内存

size:创建共享内存的大小

shmflg: IPC_CREAT:创建共享内存 IPC_EXCL:只能和前面的一起使用,如果共享内存存在则报错,还需要指定权限IPC_CREAT|0644

返回值:成功:返回共享内存ID值,失败返回-1并设置errno

1、共享内存存在
key_t key=0x1234;
int shmID=shmget(key,0,0);

2、共享内存不存在
int shmID=shmget(key,100,IPC_CREAT|IPC_EXCL|0755);

3、无法确定是否存在
int shmID=shmget(key,100,IPC_CREAT|0755);

连接共享内存:

 #include <sys/types.h>
 #include <sys/shm.h>

       void *shmat(int shmid, const void *shmaddr, int shmflg);

参数:shmid:shmget得到的ID值

shmaddr:NULL让内核自己分配地址

shmflg:0:读写都行 SHM_RDONLY:只能读

返回值:成功返回关联的内存地址,失败返回(Void*)-1

断开与共享内存的链接:

 #include <sys/types.h>
 #include <sys/shm.h>

  int shmdt(const void *shmaddr);

参数:shmaddr:shmat返回值

返回值:成功返回0,失败返回-1

设置或者删除共享内存:

#include <sys/ipc.h>
 #include <sys/shm.h>

       int shmctl(int shmid, int cmd, struct shmid_ds *buf);



           struct shmid_ds {
               struct ipc_perm shm_perm;    /* Ownership and permissions */
               size_t          shm_segsz;   /* Size of segment (bytes) */
               time_t          shm_atime;   /* Last attach time */
               time_t          shm_dtime;   /* Last detach time */
               time_t          shm_ctime;   /* Last change time */
               pid_t           shm_cpid;    /* PID of creator */
               pid_t           shm_lpid;    /* PID of last shmat(2)/shmdt(2) */
               shmatt_t        shm_nattch;  /* No. of current attaches */
               ...
           };

shmid:shmget返回的ID值

cmd:IPC_STA:获得共享内存的信息,拷贝到结构体中

IPC_SET:设置

IPC_RMID:删除:只有在最后一个进程断开连接才可以删掉  最后一个参数填NULL

当删除共享内存时,如果共享内存关联计数大于0,则不会被真正删除,但是key值变为0,当一个进程与共享内存关联之后关联引用会加1,断开后关联计数减1

shm和mmap的区别:

  1. mmap如果用于没有血缘关系的进程间通信必须使用文件,shm不需要
  2. shm操作数据比mmap快
  3. mmap比shm安全
  4. 进程退出,共享内存依然存在,进程退出,内存映射去就不存在了

相同点:mmap和shm都使用的内存地址,都可以用于有无血缘关系的进程间通信,mmap和shm读取数据后并不会消失

ftok函数:使用文件名生成key值

 #include <sys/types.h>
 #include <sys/ipc.h>

 key_t ftok(const char *pathname, int proj_id);

函数参数:

pathname:带文件路径的文件名(必须文件是存在的,对文件权限没有要求)

proj_id:只是用一个字节,取值范围:0-255

返回值:成功返回key_t key,失败返回-1

共享内存操作指令:

ipcs -a

ipcs -m

ipcs -s

ipcs -q

ipcrm -m shmid/-M keyid

消息队列:mssget 等等

信号量:semget等等

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值