分享

Socket编程心得

 逸随风清 2013-07-11

背景知识

TCP/IP模型

 

应用层

传输层(TCP/UDP)

网络层(IP)

数据链路层

 

通常的套接字是应用到传输层的接口.(有一种原始的可以直接使用IP).

传输层一般的俩个协议: UDP (User Datagram Protocol) and TCP (Transmission Control Protocol ).

 

UDP

无连接 (发送数据无需建立连接)

不可靠 (不能确保UDP数据报最终达到目的地对接收的数据不发送确认无法指定是否到达目的地数据不会重发).

速度快 (由于无需建立连接和确认信息速度也就快了).

 

TCP

面向连接 (发送数据前先要建立连接)

可靠     (当发送数据后要求对方返回一个确认信息如果没有接收到对方确认重发.)

基于字节流 (对发送的数据排序每个发送字节关联一个序列号对方根据此序列号进行数据排序确保数据的顺序).

 

三握手:

客户 ----SYN--->       服务器

客户 <--SYN and ACK--- 服务器

客户 ----SYN--->       服务器

 

端口(0 ~ 65535, (unsigned long) 216)

0 ~ 1023 一般和某些服务绑定所以一般我们不用这个范围的端口.

1024 ~ 49151 提供一般应用程序使用.(Win Socket开发选中的范围)

动态或私有端口: 49151 ~ 65535

 

IP地址

struct sockaddr_in {
    short                 sin_family;      // must be AF_INET
    unsigned short               sin_port;                 // 端口号
    struct   in_addr   sin_addr;                 // IP地址
    char                         sin_zero[8];     // 扩充
};

 

字节顺序

Intel的电脑一般都是将低地址对应实际数子的高位.

计算机用一个Short 表示1的方式:

0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,0x0F

 0    0    0    0    0    0    0   1     0    0    0     0    0     0    0    0

1本来应该是:

00 01, 计算机将其以字节为单位反转高低位: 01 00.

 

再如一个u_long类型: 4432

内存表示为: 50 11 00 00, 实际应该是: 00 00 11 51

而网络流就是按照这种顺序传输的所以要利用 htonl, htons, ntohl, ntohs四个函数来转换字节流顺序.

 

关于关闭

关闭连接有两个选择从容关闭硬关闭.

两个混淆的关闭关闭连接关闭套接字.

从容关闭一方关闭连接另一方可以继续读取网络堆栈的数据直到数据传送完毕双方都关闭了连接,可以保证在关闭之前,数据都被接收.

硬关闭只要一方关闭了连接另一方就无法接收数据数据无法传送完毕.

 

关系:

关闭连接的方式包括从容关闭连接方式  硬关闭连接方式

关闭套接字其实就是相对于操作系统而已的释放资源关闭句柄,相当于CloseHandle的意思.

关闭连接函数shutdown and WSASendDisconnect函数

关闭套接字函数closesocket(同时隐含执行shutdown函数功能

 

从容关闭的思想甲方我要关闭 -> 通知给乙方乙方得到消息后哦知道了(此时甲方还能接收数据), 乙方可以选择继续发送数据,也可以通知甲方,我也要关闭了然后调用closesocket关闭套接字 -> 方得到关闭消息,closesocket关闭套接字.

 

:客户端:服务器.

(调用shutdown(SD_SEND), 接着等待FD_READFD_CLOSE, 等到FD_CLOSE关闭套接字)

(调用 shutdown(SD_SEND), 紧着调用closesocket)

 

基本的函数:

WSAStartup   socket    bind      listen       accept     recv        send        closesocket

shutdown        connect         recvfrom        sendto     WSCleanup

getsockopt      setsockopt

 

俩大模式阻塞模式非阻塞模式.

五大模型: Select模型, WSAAsyncSelect模型, WSAEventSelect模型重叠I/O, 完成端口.

阻塞模式在哪儿阻塞?

有两个地方:

1.       等待数据的时候当数据没有到达就会被阻塞等待数据的到达.

2.       数据到达从系统缓冲区复制到用户区此过程也被阻塞.

五个模型的阻塞方式各不相同.

 

通常说的非阻塞其实是在上面提到的阻塞的第一个地方不阻塞真正实现两个地方都不阻塞的只有 重叠I/O, 完成端口 俩个模型.

 

 

阻塞模型

Socket编程心得 - Dsliu - Dspace

如果是单线程一旦阻塞程序就被操作系统换入等待队列程序就处于等待状态,(如果是GUI界面可以想象假死的状态多么难堪). 所以可以用多线程来操作例如主线程来运行GUI的消息循环创建一个线程用来等待(recv之类的函数), 创建一个线程来接处理数据.这样在其中一个线程等待的时间里可以来响应用户消息和处理数据等可以想象如果大量用户接入就要创建大量的线程对系统造成的开销很大.

 


非阻塞模式

Socket编程心得 - Dsliu - Dspace
 

可以看到程序循环检测数据浪费CPU, 如果写个程序能看到程序的占有率基本上总是100%, 对系统的资源占用很大而且比起阻塞模式而已没有什么优点非阻塞的作用主要体现在和5个模型共同协作才能体现其优点.


Select模型

Socket编程心得 - Dsliu - Dspace
 

可以同时等待多个套接字.


WSAAsyncSelect模型

Socket编程心得 - Dsliu - Dspace
 

 

WSAAsyncSelect  select模型的异步版本那么异步指的是谁和谁异步?

这里的异步应该是指目前执行WSAAsyncSelect的线程和等待数据的到达俩个流程是异步的也就是说谁也不等谁线程调用完此函数继续下下执行数据到达才发送消息给应用程序窗口接着线程就要处理这批数据了通过图看的出从缓冲区复制到用户空间的数据仍然是阻塞的这个过程类似于ReadFile, 所以还没算真正意义的(执行流程和接收数据的)异步.

 

WSAAsyncSelect  Select

WSAAsyncSelect模型与Select模型相同都可以有效的对多个套接字进行管理.

WSAAsyncSelect是基于消息的所以必须创建窗口(可以创建一个隐藏的窗口), Unix很多基于命令符界面的环境都一般用Select模型.

WSAAsyncSelect自动将套接字设置为非阻塞模式select并没有这个特性

 


WSAEventSelect模型

Socket编程心得 - Dsliu - Dspace
 

 

通过对比图可以看出WSAEventSelect  WSAAsyncSelect的唯一区别就是通知方式不同WSAAsyncSelect 是通过发送消息来通知应用程序的WSAEventSelect则是事件形式通知当然实现的形式也不相同一个是通过操作系统发送消息给窗口过程来处理一个是操作系统触发事件在应用程序端则是等待事件发生(由于等待事件是阻塞的所以要多开一个线程).


重叠I/O

Socket编程心得 - Dsliu - Dspace
 

 

对比:

Socket编程心得 - Dsliu - Dspace
 


完成端口模型

Socket编程心得 - Dsliu - Dspace
 

完成端口解决了 “one-thread-per-client” 问题.

 

网络程序开发流程:

1.       需求分析

2.       根据需求进行数据包设计(一般分为包头和包数据两部分包头用来存储包的必要信息如信息类型数据长度等)

3.       定义传输协议(如何传输).

4.       理解需求设计总体架构利用设计模式等方法进行问题分析和设计类图.

5.       实现通常要配合多线程来实现通信问题. (一般有等待客户请求线程接收数据线程发送数据线程资源清理线程).

6.       实现服务器端.

7.       实现客户端.

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多