tcp协议和udp协议的比较

tcp协议 —— 传输控制协议,面向链接的协议,类似打电话

—— 建立链接=> 进行通信 => 断开链接

—— 在通信的整个过程中全程保持连接

—— 保证了数据传递的可靠信和有序性(重点)

—— 提供了流量控制,也就是数据接收方会实时通知数据的发送缓冲区的大小

—— 是一种全双工的字节流通信方式

—— 服务器压力比较大,发送数据的效率比较低

udp协议 —— 用户数据报协议,非面向链接的协议,类似写信

—— 不需要全程保持连接

—— 不保证数据传递的可靠性和有序性

—— 不提供流量控制

—— 是全双工的数据报通信方式

—— 服务器压力比较小,发送数据的效率比较高

基于UDP的协议通信模型

服务器端:

1、创建socket,使用socket函数

2、准备通信地址,使用结构体类型;

3、绑定socket和通信地址,使用bind函数

4、进行通信,使用send/sendto/recv/recvfrom函数

5、关闭socket,使用close函数

客户端:

1、创建socket,使用socket函数

2、准备通信地址,使用服务器地址

3、进行通信,使用send/sendto/recv/recvfrom函数

4、关闭socket,使用close函数

  ssize_t sendto(int sockfd, const void *buf,size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);

功能:该函数的功能与send函数类型,只不过是通过后两个参数来指定收件人的信息

ssize_trecvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr*src_addr, socklen_t *addrlen);

功能:该函数的功能与recv函数功能相似,只不过是通过后两个参数可以得到客户端/数据发送方的通信地址,相当于来电显示的效果

 1 //使用UDP网络模型实现通信3 #include <stdio.h>4 #include <stdlib.h>5 #include <unistd.h>6 #include <sys/types.h>7 #include <netinet/in.h>8 #include <arpa/inet.h>9 #include <sys/socket.h>10 11 int main(void)12 {13     //1.创建socket,使用socket函数14     int sockfd = socket(AF_INET, SOCK_DGRAM, 0);15     if( -1 == sockfd )16     {17         perror("SOCKET");18         exit(-1);19     }20 21     printf("socket 创建成功!\n");22 23     //2.准备通信地址,使用结构体类型24 25     struct sockaddr_in addr;26     addr.sin_family = AF_INET;27     addr.sin_port = htons(8888);28     addr.sin_addr.s_addr = inet_addr("172.30.4.127");29 30     //3.绑定socket通信地址,使用bind函数31 32     int res = bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));33     if(-1== res)34     {35         perror("bind");36         exit(-1);37     }38 39     printf("绑定成功!\n");40 41     //4.进行通信,recv/recvfrom/send/sendto42 43     struct sockaddr_in recv_addr;44     socklen_t len = sizeof(recv_addr);45 46     char buf[100] ={0};47     res = recvfrom(sockfd, buf, sizeof(buf), 0 , (struct sockaddr*)&recv_add    r, &len);48     if(-1 == res)49     {50         perror("recv");51         exit(-1);52     }53 54     char * ip = inet_ntoa(recv_addr.sin_addr);55 56     printf("客户端%s发来的消息是:%s, 消息大小是:%d\n", ip, buf, res);57 58     //向客户端回发消息59     res = sendto(sockfd, "I received!", 12, 0, (struct sockaddr*)&recv_addr,    len);60     if(-1 == res )61     {62         perror("sendto");63         exit(-1);64     }65 66     printf("成功发送数据到客户端,发送的数据大小是:%d\n", res);67 68     //5.关闭socket,使用close函数69 70     res = close(sockfd);71     if( -1 == res )72     {73         perror("close");74         exit(-1);75     }76 77     return 0;78 }

线程的基本概念

线程隶属于进程,线程是属于进程内部的程序流,目前主流的操作系统都支持多进程,而每个进程的内部有可以支持多线程

进程是重量级的,每个进程都需要独立的内存空间等,因此新建进程对系统资源的消耗比较大,而线程是轻量级的,新建线程会共享所在进程的内存资源等,因此线程对系统资源的消耗比较小,当然每个线程都拥有一块独立的栈区

线程的基本操作

线程的创建

1、pthread_create函数

#include<pthread.h>

intpthread_create(pthread_t *thread, const pthread_attr_t *attr, void*(*start_routine) (void *), void *arg);

参 1:用于将新线程的编号存放在该参数指向的缓冲区中

pthread_t 类型 => typedef unsigned long int pthread_t;

不同系统中对pthtread_t的实现可能不同

参 2:给NULL表示选择默认属性即可

参 3:函数指针类型,新线程的处理函数,也就是新线程启动之后需要去执行的代码;

参 4:用于作为第三个参数所指向函数的实参

返回:成功返回0,失败返回错误编号

功能:主要用于在当前正在调用的进程中创建一个新进程

30    if( 0 != errno )

31     {

32        printf("pthread_careate:%s\n", strerror(errno));

33         exit(-1);

34     }

编译时需要加上-pthread 链接动态库 ( gcc xxx.c -pthread )

线程之间的关系

执行main函数的线程叫做主线程;

使用pthread_create函数创建出来的线程叫做子线程

主线程和子线程之间相互独立,又相互影响,当主线程结束时,会导致进程结束,而进程结束又会导致进程中的所有线程结束

pthread_t pthread_self(void);

功能:主要用于获取当前正在调用线程的编号并返回,没有出错情况

 

     int pthread_equal(pthread_t t1, pthread_tt2);

功能:主要用于判断参数指定的两个线程编号是否相等,如果相等返回非0,否则返回0,没有出错情况

线程的汇合和分离

intpthread_join(pthread_t thread, void **retval);

参 1:线程的编号

惨 2:二级指针类型的返回值

功能:主要用于汇合一个终止的线程,也就是等待第一个参数thread所指向的线程终止,如果该线

+程已经终止,则pthread_join函数立即返回,当然前提条件是:目标线程是可以等待的

+当第二个参数retval不为空时,则该函数会将所等待的目标线程的退出状态信息拷贝到

+*retval所指向的位置

18   return (void*)&sum;

32          int * pc = NULL;

33

34     errno = pthread_join(thread, (void **)&pc);

intpthread_detach(pthread_t thread);

功能:主要用于将参数指定的线程设置为分离状态,当一个分离状态的线程终止时,会自动释放资源给系统,不需要其它线程的帮助,其他线程也不能用pthread_join函数等待

线程的终止

 void pthread_exit(void *retval);

功能:主要用于终止当前正在调用的线程,通过参数返回当前线程的推出状态信息,在同一个进程中的其他线程可以通过pthread_join函数来获取该退出状态信息

线程的取消

int pthread_cancel(pthread_t thread);

功能:主要用于给参数指定的线程发送取消的请求,对于一个新创建的线程老说,默认是可以取消的

intpthread_setcancelstate(int state, int *oldstate);

参 1:用于设置新的状态

PTHREAD_CANCEL_ENABLE —— 可以被取消

              PTHREAD_CANCEL_DISABLE —— 不可以被取消

参 2:用于带出旧的状态,给NULL表示不带出函数功能

功能:主要用于设置当前线程是否允许被取消

线程的同步(重点)

基本概念

当多个线程在同一时刻同时访问同一种共享资源时,可能会造成数据的不一致和混乱等问题,此时

+就需要对多个线程进行协调,而线程之间的协调和通信就叫做线程的同步问题

使用互斥量实现线程的同步

定义互斥量                        —— pthread_mutex_t mutex;

         初始化互斥量                ——pthread_mutex_init( &mutex, NULL );

         使用互斥量行加锁              —— pthread_mutex_lock(&mutex);

         访问共享资源

         使用互斥量进行解锁            —— pthread_mutex_umlock(&mutex);

         如果不再使用,则销毁互斥量         —— pthread_mutex_destroy(&mutex);

 

使用信号量实现线程的同步

信号量 —— 本质就是一种计数器,用于控制同时访问同一种共享资源的进程/线程个数;

当信号量的初始值为1时,效果等同互斥量

#include <semaphore.h>

定义信号量                            —— sem_t sem;

         初始化信号量                     —— sem_init(&sum, 0, 初始值)

         获取信号量,也就是信号量减1        —— sem_wait(&sem);

         访问共享资源

         释放信号量,也就是信号量加1        —— sem_post(&sem);

         如果不再使用,则销毁信号量              —— sem_destroy(&sem) 

=====================================================================================

终端规范模式开启于关闭,使得缓冲和编辑失效

#include <termios.h>

#include<unistd.h>

 int tcgetattr(int fd, structtermios *termios_p);

参 1:设备终端的文件描述符:0——标准输入,1——标准输出,2——标准错误

参 2:struct termios original_mode{

……

tcflag_t c_lflag;    //本地模式标志,控制终端编辑功能

                 cc_t     c_cc[NCCS];

};

c_lflag:ICANON —— 使用标准输入模式

eg:original_mode.c_lflag&= ~ICANON  ——  去除标准输入模式

ECHO   —— 回显功能

eg:original_mode.c_lflag&= ~ECHO   —— 关闭回显功能

c_cc[NCCS]:控制字符,用于保存终端驱动程序中的特殊字符,如输入结束符等

NCCS: VMIN —— 非规范模式读取时的最小字符数

eg:original_mode.c_c[VMIN] =1

功能:用于获取与终端相关的参数,返回的结果保存在termios结构体中

int tcsetattr(int fd, int optional_actions, const struct termios*termios_p);

参 1:fd为打开的终端文件描述符,一般给 0;

参 2:optional_actions用于控制修改起作用的时间

* TCSANOW:     不等数据传输完毕就立即改变属性

参 3:而结构体termios_p中保存了要修改的参数

返回:函数在成功的时候返回0,失败的时候返回-1

功能:用于设置终端参数参数参数

5 int _getchar(char * c_num)6 {7     //设置两个结构体用以存储终端相关信息8     struct termios oldmode;9     struct termios newmode;10 11     //获取与终端相关的参数,将结果返回给结构体12     if ( !0 == tcgetattr(0,&oldmode) )13     {14         perror("TCGETATTR ERROR");15         return -1;16     }17 18     //将原来的参数copy给新的结构体用以修改不影响原系统设置  19     newmode = oldmode;20 21     //ICANON摆在哦混输入模式,~ICANON去除该模式22     newmode.c_lflag &= ~ICANON;23     //当输入错误时不希望错误选项回显则23      newmode.c_lflag &= ~ECHO;2324     //AMIN非规范模式设置1,告诉驱动程序一次只读一个字符25     newmode.c_cc[VMIN] = 1;26 27     //在获取输入字符时,使终端模式处于非规模模式下,关闭缓冲与编辑28     if( -1 == tcsetattr(0, TCSANOW, &newmode) )29     {   30         perror("TCSETATTR ERROR");31         return -1;32     }33 34     *c_num = getchar();35 36     //获取成功后还原终端规范模式下37     if ( -1 == tcsetattr(0, TCSANOW, &oldmode) )38     {39         perror("TCGETATTR ERROR");40         return -1;41     }42 43     return 0;44 }45

UNIX_C 高级编程七相关推荐

  1. ASP 3.0高级编程(七)

     来    源: 互联网  作    者: 不祥  发表日期: 2005-12-17 16:35:42  阅读次数: 106  文章标题:ASP → ASP 3.0高级编程(七)  查看权限: 普通文 ...

  2. 解读经典《C#高级编程》第七版 Page79-93.对象和类型.Chapter3

    前言 本篇我们继续讲解本章其余的部分:构造函数.只读字段.匿名类型.结构详解.部分类.静态类.Object类.扩展方法,等. 01 类 构造函数 构造函数是一种特殊的方法: 与类同名 没有返回值,甚至 ...

  3. 解读经典《C#高级编程》第七版 Page32-38.核心C#.Chapter2

    前言 接下来讲讲预定义数据类型.关于数据类型,其实是非常值得透彻研究的. 01 预定义数据类型 值类型和引用类型 C#将把数据类型分为两种,值类型和引用类型,值类型存储在堆栈上,引用类型存储在托管堆上 ...

  4. 不为人知的网络编程(七):如何让不可靠的UDP变的可靠?

    为什么80%的码农都做不了架构师?>>>    本文内容来自学霸君资深架构师袁荣喜的技术分享. 1.前言 最近和很多实时音视频领域的朋友交流中都有谈论到 RUDP(Reliable ...

  5. (三) 一起学 Unix 环境高级编程 (APUE) 之 文件和目录

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  6. c++面向对象高级编程 总目录

    本文是对学习侯捷视频 c++面向对象高级编程系列博客的目录总索引. c++面向对象高级编程 学习一 不带指针的类: 访问私有成员变量的方式,内联inline,常量成员函数,构造函数,值传递,引用传递, ...

  7. 《Unix环境高级编程》学习笔记:从点到面

    以前在课堂上学习过<Unix初级教程(第四版)>,对于Unix有了一点了解.由于以后使用的需要,要对它进行比较深入的学习,为此需要阅读不少的书籍,这本<Unix环境高级编程>便 ...

  8. Unix环境高级编程 笔记

    Unix环境高级编程(第二版)学习笔记 这是一次较长时间的整理,然而跳跃了一些章节和很多知识点,仍然是很不完善很不全面的. 前言 操作系统某些问题 严格意义上,可将操作系统定义为一种软件,它控制计算机 ...

  9. hypermill五轴再加工_【秒杀】hyperMILL2018三四五轴基础到高级编程视频教程,带你快速熟悉五轴编程...

    特别申明 本套视频教程为收费教程 特价一天98元 需要本套教程请加微信:16395136 01.hyperMILL 2018 基 础建模视频教程 Hypercad-s教程 第01章:自定义软件 [开] ...

最新文章

  1. MindInsight计算图可视设计
  2. python【力扣LeetCode算法题库】面试题59 - II- 队列的最大值
  3. 微软发布 Windows 10 预览版 Build 21343:此电脑和回收站等启用全新图标
  4. python在线作业_南开大学20春学期《Python编程基础》在线作业参考答案
  5. [转载] Java获取一个类继承的父类或者实现的接口的泛型参数
  6. 【Linux/Ubuntu】查询文件和文件夹大小
  7. python网络编程-socketserver模块
  8. 500能不能配个玩英雄联盟的电脑?
  9. [转]nodejs Error: request entity too large解决方案
  10. 将时间戳转为中国标准时间
  11. Android关于Activity屏蔽/拦截Home键
  12. The Preliminary Contest for ICPC Asia Shanghai 2019 B. Light bulbs(卡了线段树空间的思维题)
  13. 在Illustrator和手绘文章中创建矢量图形
  14. 5、流程变量Variables
  15. Windows系统配置
  16. 0002数学建模的重要意义
  17. 校园安防之高清IP摄像头全终端无插件直播视频流媒体服务EasyNVR校园监控系统方案
  18. vue实例和组件的区别
  19. 怎么把柱形图和折线图放在一起_EXCEL中统计图表怎么合并在一起?(如柱形图和折线图)...
  20. 洛谷P1606 Lilypad Pond G

热门文章

  1. 私域流量暗战,品牌如何主宰下半场?
  2. IDEA远程提交hadoop任务时出现的错误
  3. 重装Win10系统之U盘启动盘的制作(详细教程)
  4. 转载 禁止ie浏览器打开
  5. eigen坐标变换_Eigen实现坐标转换
  6. 使用ExcelJs导出表格设置样式、添加边框
  7. cad调了比例因子没反应_大神们都在用的9个CAD制图技巧,你会用几个?
  8. android远程控制(三)----通过后台服务实现系统点击事件模拟
  9. Web项目经理手册之项目经理需要铭记在心的话
  10. web项目经理手册-项目经理需要铭记在心...