【2016/1/27】 网络编程 - TCP协议

网络编程

2016-1-27:
网络协议: 用结构体(报头)来描述数据包的属性与内容来处理
- 有源IP和目标IP
- 网络协议层层封装 HTTP <- TCP <- IP <- 机器属性
- IP 同时被 TCP 和 UDP 封装 , IP本身是不可靠的
- TCP以应用层的技术,保障了协议的可靠程度

B/S方式
HTTP: 通用的客户端协议 让任何人可以轻易的使用浏览器来访问服务端

C/S方式
TCP:
1. TCP在拥堵时会自动收缩自己的传输范围(用数学公式推算的)
2.【滑动窗口】技术:不断清除返回的队列内容来缩减队列
3. 基于流的连续传输:保障所有的包按顺序到达
UDP: 不保障可靠和顺序,但是效率高

    短链接:瞬间断开
    长链接:一直建立等待超时再断开的链接

socket:
一个描述符 代表的是一片内存区域
含有接受缓存和发送缓存 通过内核将信息发到网卡上发送
— domian 使用AF_UNIX 可以使用本地模式 使用本地套结字通信
— 多进程的socket之间没有意义,但是fork()是可以放在accept之前的,但是要用AF_UNIX来渡过去

单个主机内,每一个进程需要采用不同的端口号来使用与标识
客户端的端口号可以人为指定也可以系统分配
上下限:(0-65535)short类型
    netstat -antplue  #shell查看各种有关端口的信息
    tcpdump port <端口号> -i <网卡> -nn #查看端口的信息

DDOS攻击: 不断地连环ping目标网卡 然后使之缓存区立即溢出 无法接受数据
— 低级 有效 不可防范

TCP编程:
eg:
https://github.com/KhalilWang/IPC_samples/tree/master/Socket

客户端:
           1.socket(AF_INET, SOCK_STREAM, 0);      //创建套结字
           2.connect(sockfd, *sa_addr, addrlen);   //连接端口
           3.send() / recv();                      //发送/接受数据
           4.close(fd);                            //退出

服务端:


           1.socket(AF_INET, SOCK_STREAM, 0);       //创建套结字
           2.bind(sockfd, *sa_addr, addrlen);       //绑定端口
           3.listen(sockfd, backlog);               //监听端口4.accept(sockfd, *addr, *addrlen);      //等待接受请求5.fork() / pthread_create();            //创建进线程处理
           6.close(fd);                             //退出

listen中的backlog是可以允许的排队人数
— 真正的人数是 backlog * 3 / 2 + 1
accept中的addr接收的是连接人的addr信息
accept返回的是一个sockfd!CS之间的通信由此开始!
通常在accept之后创建进线程来处理新的fd,
然后主进程继续accept来接受请求
进程立即fork()(线程没有独立空间,不太适合存储accept的返回值)
线程则需要将fd存储于栈上,使用同步技术防止fd被覆盖

对于描述符的使用:(适合tcp, 但是这两个函数和协议无关)

           send(sockfd, *buf, len, flags);
           recv(sockfd, *buf, len, flags);

其实就是对于read() / write()的封装

   struct sockaddr{
       sa_family_t sa_family  ;
       char        sa_data[14];
   }               //原版的sockaddr地址信息
   新版: sockaddr_in 将sa_family 转换为连续的几个变量
          sa_family_t ->  sin_family + sin_port(short) + sin_addr(32位整形)
           宏定义的##意思是将后面的的变量转为字符补在后面

*一般采用sockaddr_in 强转为 sockaddr 使用
端口信息采用了网络字节序:
htonl()/htons() host to network long/short 将端口号进行网络字节序转化
sin_addr -> 这个结构体变量是宏定义: 接受本网段还是全网的连接
IP地址是字符串的地址 是一个16字节的char数组 存储的IPV4的字符串
使用inet_aton()来将字符串进行网络字节序转换 inet_ntoa()反之

*tip: 网络传输时一定要注意内存对齐!

粘包问题:收包的时候没有区分好数据边界
解决方法:发每一个包之前自己做一个报头,分两次收报头,再收数据:
struct head{
int ctl;
int size;
}
根据size 的值收第二个包 防止粘包现象

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值