回忆昨天内容
一、基于TCP的编程实现
模型

实现
服务器端  socket(2)   bind(2)   listen(2)  accept(2)
客户端    socket     connect
地址家族
    通用地址家族
    ipv4地址家族   
    ipv6地址家族
将代码封装,头文件   源文件    多文件编译链接

今天内容:
一、基于TCP的实现
    一次连接,多次通话
    客户端和服务器端连接上以后,如果客户端不发送exit,就一直保持着连接。也就是说
客户端发送exit时终止和服务器端的连接。
二、并发服务器的实现
    使用多进程实现服务器的并发。
    进程模型   一个父进程  多个子进程
    父进程负责的任务:
        负责受理客户端的连接    
        cfd=accept(2)
        创建子进程
        关闭cfd
        负责回收子进程的资源
    子进程负责的任务:
    负责具体的和客户端的沟通
    close(sfd)
    业务处理
    关闭(cfd)
    exit(3)

setsockopt(2)
三、基于udp的编程实现
    模型:
    服务器端
    1 创建一个通讯设备 返回该设备的文件描述符(sfd) socket(2)
    2 将sfd绑定本地地址和端口  bind(2)
     while(1){
        接收客户端的数据 recvfrom(2)
        处理客户端的数据
        响应客户端    sendto(2)
    }
    客户端模型
    1 创建一个通讯设备 返回该设备的文件描述符(sfd)
    2 向服务器发送数据  sendto(2)
    3 阻塞等待服务器的响应消息   recvfrom(2)
    4 处理服务器响应
    5 关闭文件描述符 close(sfd)

recvfrom(2)    sendto(2)

recvfrom(2)
       #include <sys/types.h>
       #include <sys/socket.h>

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
    功能:从socket上接收一个消息
    参数:
        sockfd  指定socket  从这个socket上接收消息
        buf  存储接收到的结果的地址
        len  指定了buf的大小
        flags  0
        src_addr 存储消息的来源地址
        addrlen 值——结果参数   src_addr的尺寸
    返回值:成功 返回接收到的字节数
        失败 -1  errno被设置

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

功能:在socket上发送一条消息
参数:
    sockfd 指定了文件描述符  向这个文件描述符写数据
    buf  要写的数据的地址
    len    指定buf中的有效字节数
    flags   0
    dest_addr    存放目标地址
    addrlen    指定目标地址的大小
返回值: 成功 返回发送出去的字节数
    失败 -1  errno被设置
    
    服务器端 参见 userver.c
    客户端   参见 uclient.c
四、线程的基础
    进程  进程是资源分配的基本单位。每个进程都有自己的pid PCB
    线程  是执行的基本单位  每个线程有自己的tid 也有自己的TCB
    
    一个进程中可以有多个线程  进程中的线程共享进程的资源  每个线程也有自己的私有资源
    线程间的通讯和切换比进程间的通讯和切换开销要小很多
    但是注意一个进程中多个线程争抢共享资源
    
    多个线程争抢的共享资源称作 临界资源
    如何在一个进程中创建一个线程
    pthread_create(3)
    #include <pthread.h>

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                          void *(*start_routine) (void *), void *arg);
    功能:创建一个新的线程
    参数:
        thread  新创建的线程的id存储到这个参数指定的地址空间里
        attr  NULL   默认属性
        
        start_routine 线程函数
        arg   是线程函数的唯一参数
    返回值:成功0
        错误  非0的错误码   thread未定义
    Compile and link with -pthread 编译和链接使用pthread库
    void *(*start_routine) (void *)

举例说明   新线程的创建  pthread_c.c

获取自己的tid
    pthread_self(3)
     #include <pthread.h>

pthread_t pthread_self(void);

Compile and link with -pthread 编译和链接使用pthread库
    功能:获取当前线程的tid
    参数:无
    返回值:总是成功 返回调用的线程的tid
    
    
五、线程的终止、汇合、分离
    
    1.线程的终止
        1)使用return结束线程函数   不能使用exit(3)
        2)使用pthread_exit(3) 终止当前线程
        3)可以使用pthread_cancel(3)取消某一个线程
pthread_exit
       #include <pthread.h>

void pthread_exit(void *retval);

Compile and link with -pthread.
    功能:终止当前线程
    参数:
        retval 通过这个值传递给另外一个线程(同一进程中的线程,该线程调用了pthread_join(3))
    返回值: void 不返回给调用者
pthread_cancel(3)
 #include <pthread.h>

int pthread_cancel(pthread_t thread);

Compile and link with -pthread.
    功能:发送一个取消请求给线程,将其终止   取消线程终止时终止状态标记为PTHREAD_CANCELED,按照int类型访问,输出为-1。代码参见day14,pthread_e.c
    参数:
    thread 目标线程的tid
    返回值:成功 0
        错误 非0
pthread_detach(3) 线程的分离
       #include <pthread.h>

int pthread_detach(pthread_t thread);

Compile and link with -pthread.
    功能:将线程标记为分离的线程,当其终止时,资源自动释放回系统
    参数:
    thread  指定要分离的线程tid
    返回值:成功  返回0
        错误 错误编号

t_net.h

#ifndef T_NET_H_
#define T_NET_H_#include<sys/socket.h>#include<sys/types.h>
#include<netinet/in.h>
#include<arpa/inet.h>typedef struct sockaddr SA;//通用地址typedef struct sockaddr_in SA4;//ipv4地址//完成socket bind(2)int s_bind(int domain,int type,in_port_t port);int no_accept(int fd);int h_accept(int fd);int t_listen(int domain,int type,in_port_t port,int backlog);
#endif

t_net.c

#include<t_stdio.h>
#include"t_net.h"int s_bind(int domain,int type,in_port_t port){SA4 serv;//具体ipv4地址//创建socket 返回该设备的文件描述符 int sfd=socket(domain,type,0);if(sfd==-1) E_MSG("socket",-1);//初始化服务器的ip地址和端口serv.sin_family=AF_INET;serv.sin_port=htons(port);serv.sin_addr.s_addr=htonl(INADDR_ANY);//本地所有端口的ip地址//将sfd绑定到本地地址int b=bind(sfd,(SA *)&serv,sizeof(serv));if(b==-1) E_MSG("bind",-1);return sfd;
}int no_accept(int fd){//没有来电显示int cfd=accept(fd,NULL,NULL);if(cfd==-1) E_MSG("accept",-1);return cfd;
}
int h_accept(int fd){//有来电显示SA4 cli;char ip[32];socklen_t len;len=sizeof(SA4);int cfd=accept(fd,(SA *)&cli,&len);if(cfd==-1) E_MSG("accept",-1);printf("%s\n",inet_ntop(AF_INET,&cli.sin_addr,ip,32));return cfd;
}
int t_listen(int domain,int type,in_port_t port,int backlog){int fd=s_bind(domain,type,port);if(fd==-1) return -1;listen(fd,backlog);return fd;
}

doit.h

#ifndef DO_IT_H_
#define DO_IT_H_#include<unistd.h>#include<ctype.h>void do_main(int cfd);#endif

doit.c

#include"doit.h"void do_main(int fd){char buf[128];//从连接描述符里读取客户端发送来的数据到buf中int r=read(fd,buf,128);//处理客户端数据for(int i=0;i<r;i++)buf[i]=toupper(buf[i]);//响应客户端write(fd,buf,r);return;}

pthread_c.c

#include<pthread.h>
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
//线程执行函数
void *doit(void *arg){printf("%s,pid=%d\n",(char *)arg,getpid());    printf("tid:%lu\n",pthread_self());return NULL;
}
int main(void){pthread_t tid;//创建新的线程pthread_create(&tid,NULL,doit,"new");//这个时候,是几个线程在执行?//这两个线程是异步的,没有sleep就不确定谁先执行sleep(1);doit("main");    return 0;
}

userver.c

#include<t_net.h>
#include<t_stdio.h>
#include<ctype.h>
#include<unistd.h>
int main(){char buf[256];SA4 cli;socklen_t len;//socket bindint fd=s_bind(AF_INET,SOCK_DGRAM,4444);if(fd==-1) return -1;while(1){len=sizeof(SA4);//阻塞等待客户端请求的数据int rcv=recvfrom(fd,buf,256,0,(SA *)&cli,&len);if(rcv==-1) E_MSG("recvfrom",-1);//获取到客户端请求的数据,处理数据for(int i=0;i<rcv;i++)buf[i]=toupper(buf[i]);//将处理结果响应给客户端sendto(fd,buf,rcv,0,(SA *)&cli,sizeof(SA4));}close(fd);return 0;
}

uclient.c

#include<t_net.h>
#include<t_stdio.h>
#include<unistd.h>
#include<string.h>
int main(int argc,char* argv[]){char *msg="hello beijing\n";SA4 serv;char buf[256];//创建socket设备 返回该设备的文件描述符int fd=socket(AF_INET,SOCK_DGRAM,0);if(fd==-1) E_MSG("socket",-1);//初始化servserv.sin_family=AF_INET;serv.sin_port=htons(4444);inet_pton(AF_INET,argv[1],&serv.sin_addr);//向服务器发送消息int s=sendto(fd,msg,strlen(msg),0,(SA *)&serv,sizeof(SA4));if(s==-1) E_MSG("sendto",-1);//阻塞等待服务器的响应int rcv=recvfrom(fd,buf,256,0,NULL,NULL);if(rcv==-1) E_MSG("recvfrom",-1);//处理响应的消息write(1,buf,rcv);//关闭fdclose(fd);return 0;
}

UnixC的第十三天相关推荐

  1. 2021年大数据HBase(十三):HBase读取和存储数据的流程

    全网最详细的大数据HBase文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 系列历史文章 HBase读取和存储数据的流程 一.HBase读取数据的流程 ...

  2. 十三水牌型 图片_鬼灭之刃:鳄鱼揭开十三型的秘密,缘一亲自演示

    鬼灭之刃192话的情报已经公开,鳄鱼并没有持续更新决战现场四柱的最新情况,而是将镜头对准了炭治郎和无惨的战斗.如网友所料,炭治郎这次回归,确实已经在梦中学会了日之呼吸十三型.通过炭治郎的记忆,作者鳄鱼 ...

  3. 【Visual C++】游戏开发笔记十三 游戏输入消息处理(二) 鼠标消息处理

    本系列文章由zhmxy555编写,转载请注明出处. http://blog.csdn.net/zhmxy555/article/details/7405479 作者:毛星云    邮箱: happyl ...

  4. NeHe OpenGL第三十三课:TGA文件

    NeHe OpenGL第三十三课:TGA文件 加载压缩和未压缩的TGA文件: 在这一课里,你将学会如何加载压缩和为压缩的TGA文件,由于它使用RLE压缩,所以非常的简单,你能很快地熟悉它的.   我见 ...

  5. java基础(十三)-----详解内部类——Java高级开发必须懂的

    java基础(十三)-----详解内部类--Java高级开发必须懂的 目录 为什么要使用内部类 内部类基础 静态内部类 成员内部类 成员内部类的对象创建 继承成员内部类 局部内部类 推荐博客 匿名内部 ...

  6. 谭浩强《C++程序设计》书后习题 第十三章-第十四章

    2019独角兽企业重金招聘Python工程师标准>>> 最近要复习一下C和C++的基础知识,于是计划把之前学过的谭浩强的<C程序设计>和<C++程序设计>习题 ...

  7. 第十三届光华工程科技奖名单揭晓!这40位专家和1个团体获奖

    11月8日,第十三届光华工程科技奖揭晓仪式在北京隆重举行.工程科技是推动人类进步的发动机,是产业革命.经济发展.社会进步的有力杠杆.光华工程科技奖由中国工程院主管,目前已是第十三届,被誉为" ...

  8. 首长,Redis性能优化十三条军规立好了,请过目~

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 前言 Redis作为高性能的内存数据库,在大数据量的情况下 ...

  9. 孙立岩 python-basic: 用于学习python基础的课件(十三十四 十五)

    十三 函数 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段.函数能提高应用的模块性,和代码的重复利用率.你已经知道Python提供了许多内建函数,比如print().但你也可以自己创 ...

  10. 18年第十三届黑龙江省赛

    2018年第十三届黑龙江省赛 现在的心情挺神奇的0.0,第一次出去参加ACM比赛,连着两场,黑龙江省赛和东北四省赛,感觉运气还是挺好的,黑龙江省赛(银)铜,东北四省赛铜,最大的感受就是感觉没有想象中的 ...

最新文章

  1. AIOps-一位研发工程师的学习笔记
  2. java 常量pi_JAVA的常量
  3. ❀❀ selenium 学习网站 ★★★★★
  4. 试图安装客户出现SSR问题的Spartacus Storefront时遇到的错误消息
  5. [html] 说下你对组件、模块、元素的理解,它们的区别在哪里?
  6. java 输出流_Java中输入输出流方法总结
  7. 大数据是如何助德国队打进欧洲杯半决赛的?
  8. 【更新】Infragistics Ultimate UI for Windows Forms v18
  9. Linux内存管理:内存寻址之分段机制与分页机制
  10. python编写一个简单的程序验证码_针对验证码,做一个简单的自动网上签到程序(一)...
  11. aws rds监控慢sql_如何使用Web控制台和AWS CLI停止AWS RDS SQL Server
  12. POJ3274 Gold Balanced Lineup【Hash函数】
  13. 两组树形数据的比对_Python数据分析-可视化“大佬”之Seaborn
  14. 时间序列深度学习:状态 LSTM 模型预测太阳黑子(二)
  15. IDEA中Activate Power Mode插件 取消抖动
  16. 使用GoKart对Go代码进行静态安全分析
  17. delphi 访问https 接口
  18. 用计算机建立电子表格,求计算机作业电子表格演示文稿。
  19. 洛谷P【P5708】三角形面积java写法
  20. Java面试题大全(part_4)

热门文章

  1. matlab fread函数详解
  2. Visio2019自动闪退问题
  3. c语言汇率转换代码_C语言人民币转换代码..doc
  4. Axure RP 9 最新版授权与汉化
  5. python编程是什么东西_编程python是什么
  6. 【C++】运行MSDEV.EXE错误0xc0000142
  7. C8051单片机在交流变频调速系统中的应用(收集)
  8. 北斗导航 | 基于奇偶矢量法的RAIM之SSE探索(附奇偶矢量法源代码)
  9. 关于最近几次给客户做系统 DEMO的感悟总结
  10. ctfshow萌新赛经验总结