TCP/IP的Socket编程
1. TCP/IP、UDP的基本概念
TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,他是一个工业标准的协议集,它是为广域网设计的。其中包含了很多其他的协议,不过以TCP和IP协议为代表。UDP(User Data Protocl),即用户数据报协议,是与TCP相对应的协议,它属于TCP/IP协议族中的一个。TCP/IP进行数据传输主要分为两个过程:建立连接过程和数据传输过程。
- TCP/IP协议通过三次握手建立一个可靠的连接,步骤:
- 第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
- 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
- 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
- 数据传输过程:发送端发送数据,然后进入等待ACK确定信号状态,随后接收端接收到数据,发送ACK确认信号,发送端接收到ACK后才发送下一组数据,同时发送端有一个定时器,定时时间到了没有接收到ACK,就认为发送失败了,进行重新发送。因为发送端发送完数据后处于等待状态,因此为了提高效率,引入“滑动窗口”的概念,就是发送的时候一次发送多组数据,相当于窗口的大小,然后当接收到第一个ACK后,就将窗口向后移动一个数据,就形成了滑动窗口的情况。
下表显示了协议间的关系:
2. Socket的基本概念

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口,在设计模式中,Socket就是一个门面模式,它把复杂的TCP/IP协议族隐藏在了Scoket接口的后面,让Socket去组织数据,以符合指定的协议。
3. Socket的使用
举个简单的例子先:你要打电话给一个朋友,先拨号,朋友听到电话铃声后提取电话,这时你和你的朋友就建立起了连接,就可以讲话了,等交流结束,挂断电话结束此次交谈,这个生活场景的例子就解释了TCP/IP的工作原理和流程,其具体的流程图如下所示:

- 使用WSAStartup()函数检查系统协议栈安装情况
- 使用socket()函数创建服务器端通信套接口
- 使用bind()函数将创建的套接口与服务器地址绑定
- 使用listen()函数使服务器套接口做好接收连接请求准备
- 使用accept()接收来自客户端由connect()函数发出的连接请求
- 根据连接请求建立链接后,使用send()还念书发送数据,或者使用recv()函数接收数据
- 使用closesocket()函数关闭套接口(可以先用shutdown()函数吸纳关闭读写通道)
- 最后调用WSACleanup()函数结束Winsock Sockets API
- 使用WSAStartup()函数检查系统协议栈安装情况
- 使用socket()函数创建客户端套接口
- 使用connect()函数发出与服务器建立连接的请求(调用前可以不用bind()端口号,由系统自动完成)
- 连接建立后使用send()函数发送数据,或使用recv()函数接收数据
- 是哟个closesocket()函数关闭套接口
- 最后掉压迫能够WSACleanup()函数,结束Winsock Sockets API
4. Socket的send和recv函数
socket的发送和接收缓存区是两个相互独立的缓存区。socket的send和recv函数分为阻塞模式的和非阻塞模式的,在定义socket的时候,默认设置为了阻塞模式,而后如果想要改变为非阻塞模式,只需使用ioctlsocket函数进行设置即可。非阻塞模式一旦调用即刻返回,因此如果传输数据较为稀疏,则会经常返回失败信息,为此一般使用循环来接收数据。而常用的方式是阻塞模式,send函数没啥问题,而recv函数一般配合select函数,可以做到虽然recv是阻塞的,但是合起来的效果是阻塞一段时间的方式。下面给出send和recv函数的工作流程。
- 阻塞模式下的send和recv函数
int send( SOCKET s,const char FAR *buf,int len,int flags );
不论是客户还是服务器应用程序都用send函数来向TCP连接的另一端发送数据。
客户程序一般用send函数向服务器发送请求,而服务器则通常用send函数来向客户程序发送应答。
该函数的第一个参数指定发送端套接字描述符;
第二个参数指明一个存放应用程序要发送数据的缓冲区;
第三个参数指明实际要发送的数据的字节数;
第四个参数一般置0。
这里只描述同步Socket的send函数的执行流程。当调用该函数时,send先比较待发送数据的长度len和套接字s的发送缓冲的长度,如果len大于s的发送缓冲区的长度,该函数返回SOCKET_ERROR;如果len小于或者等于s的发送缓冲区的长度,那么send先检查协议 是否正在发送s的发送缓冲中的数据,如果是就等待协议把数据发送完,如果协议还没有开始发送s的发送缓冲中的数据或者s的发送缓冲中没有数据,那么 send就比较s的发送缓冲区的剩余空间和len,如果len大于剩余空间大小send就一直等待协议把s的发送缓冲中的数据发送完,如果len小于剩余 空间大小send就仅仅把buf中的数据copy到剩余空间里(注意并不是send把s的发送缓冲中的数据传到连接的另一端的,而是协议传的,send仅仅是把buf中的数据copy到s的发送缓冲区的剩余空间里)。如果send函数copy数据成功,就返回实际copy的字节数,如果send在copy数据时出现错误,那么send就返回SOCKET_ERROR;如果send在等待协议传送数据时网络断开的话,那么send函数也返回SOCKET_ERROR。
要注意send函数把buf中的数据成功copy到s的发送缓冲的剩余空间里后它就返回了,但是此时这些数据并不一定马上被传到连接的另一端。
注意:在Unix系统下,如果send在等待协议传送数据时网络断开的话,调用send的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。
int recv( SOCKET s,char FAR *buf,int len,int flags);
不论是客户还是服务器应用程序都用recv函数从TCP连接的另一端接收数据。
该函数的第一个参数指定接收端套接字描述符;
第二个参数指明一个缓冲区,该缓冲区用来存放recv函数接收到的数据;
第三个参数指明buf的长度;
第四个参数一般置0。
这里只描述同步Socket的recv函数的执行流程。当应用程序调用recv函数时,recv先等待s的发送缓冲 中的数据被协议传送完毕,如果协议在传送s的发送缓冲中的数据时出现网络错误,那么recv函数返回SOCKET_ERROR,如果s的发送缓冲中没有数 据或者数据被协议成功发送完毕后,recv先检查套接字s的接收缓冲区,如果s接收缓冲区中没有数据或者协议正在接收数据,那么recv就一直等待,只到 协议把数据接收完毕。当协议把数据接收完毕,recv函数就把s的接收缓冲中的数据copy到buf中(注意协议接收到的数据可能大于buf的长度,所以 在这种情况下要调用几次recv函数才能把s的接收缓冲中的数据copy完。recv函数仅仅是copy数据,真正的接收数据是协议来完成的),recv函数返回其实际copy的字节数。如果recv在copy时出错,那么它返回SOCKET_ERROR;如果recv函数在等待协议接收数据时网络中断了,那么它返回0。
2. 非阻塞模式
非阻塞模式就是一旦调用,如果不满足copy条件,则函数马上返回失败信息。
5. Winsock编程流程(以服务器端为例)
1. 使用WSAStartup()装载检查TCP/IP协议
2. 创建套接字,有三种类型的套接字供选择:流式套接字(用于TCP),数据报套接字(UDP)和原始套接字(底层协议)
3. 将创建好的套接字和IP地址以及端口进行绑定
4. 使用getsockopt获得套接口的参数,使用setsockopt设置套接口的参数(主要设置套接口的收发缓存大小),使用ioctlsocket
设置阻塞还是非阻塞的模式(这里的阻塞和非阻塞模式指的是API函数是否调用完马上返回)
5. 进行通信,在通信的部分,windows socket给我们提供了五种I/O模型用于收发通信:(他们都可以和阻塞或非阻塞函数一起
使用)
a. select模型,常用的模型,以select函数为核心,可以监控套接口是否有数据收发。它是同步模型。
b. WSAAsyncSelect模型,异步I/O模型,利用windows的消息机制实现异步接收,需要有窗口接收消息,只有接收数据是
异步的。
c. WSAEventSelect 模型,异步I/O模型,通过事件触发来实现异步接收,它不需要接收窗口。
d. 重叠模型:比较完美的模型。
e. 完成端口:最为复杂的I/O模型,当需要一个进程管理很多的套接口的时候,很适合使用这种模型。
6. 使用closesocket()函数关闭套接口的收发。
7. 使用WSACleanup()函数卸载TCP/IP协议。
TCP/IP的Socket编程的更多相关文章
- ios开发网络知识 TCP,IP,HTTP,SOCKET区别和联系
TCP,IP,HTTP,SOCKET区别和联系 网络由下往上分为: 对应 物理层-- 数据链路层-- 网络层-- IP协议 传输层-- ...
- 网络编程——基于TCP协议的Socket编程,基于UDP协议的Socket编程
Socket编程 目前较为流行的网络编程模型是客户机/服务器通信模式 客户进程向服务器进程发出要求某种服务的请求,服务器进程响应该请求.如图所示,通常,一个服务器进程会同时为多个客户端进程服务,图中服 ...
- TCP/IP协议网络编程以及UDP和TCP之传输协议
1.什么是TCP/IP协议? 网络编程协议有很多,目前应用最广泛的是TCP/IP协议(Transmission Control Protocal/Internet Protoal 传输控制协议/英特网 ...
- 网络协议HTTP、TCP/IP、Socket
网络协议HTTP.TCP/IP.Socket 网络七层由下往上分别为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层. 其中物理层.数据链路层和网络层通常被称作媒体层,是网络工程师所研究的 ...
- Linux内核 TCP/IP、Socket参数调优
Linux内核 TCP/IP.Socket参数调优 2014-06-06 Harrison.... 阅 9611 转 165 转藏到我的图书馆 微信分享: Doc1: /proc/sy ...
- 基于TCP(面向连接)的Socket编程
基于TCP(面向连接)的Socket编程 一.客户端: 1.打开一个套接字(Socket); 2.发起连接请求(connect); 3.如果连接成功,则进行数据交换(read.write.send.r ...
- TCP/IP、SOCKET、HTTP之间的联系与区别
主要内容: 1.网络的七层协议 2.TCP/IP.SOCKET.HTTP简介 3.TCP连接.HTTP连接.Socket连接的区别 一.网络的七层协议 网络七层由下往上分别为物理层.数据链路层.网络层 ...
- 基于TCP/UDP的socket编程
基于TCP(面向连接)的socket编程服务器端顺序: 1. 创建套接字(socket) 2. 将套接字绑定到一个本地地址和端口上(bind) 3. 将套接字设为监听模式,准备接收客户请求(liste ...
- TCP/IP以及Socket聊天室带类库源码分享
TCP/IP以及Socket聊天室带类库源码分享 最近遇到个设备,需要去和客户的软件做一个网络通信交互,一般的我们的上位机都是作为客户端来和设备通信的,这次要作为服务端来监听客户端,在这个背景下,我查 ...
随机推荐
- 深入理解 CSS3 弹性盒布局模型
Web 应用的样式设计中,布局是非常重要的一部分.布局用来确定页面上不同组件和元素的尺寸和位置.随着响应式用户界面的流行,Web 应用一般都要求适配不同的设备尺寸和浏览器分辨率.响应式用户界面设计中最 ...
- CSS3必须要知道的10个顶级命令
1.边框圆角(Border Radiuas) 这个是我们在平常很常用的吧,以前我在用div圆角的时候,特别特别的痛苦,不管是用CSS来画圆角,还是用图片来画圆角都不那么容易,但是现在好了,在CSS3中 ...
- spring 控制事务
<!-- 对数据源进行事务管理 --> <bean id="transactionManager" class="org. ...
- HDU 5023 A Corrupt Mayor's Performance Art(线段树区间更新)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5023 解题报告:一面墙长度为n,有N个单元,每个单元编号从1到n,墙的初始的颜色是2,一共有30种颜色 ...
- 揭露QPS增高后的秘密
导读 很多人在实际的开发中害怕系统的QPS增高,因为觉得QPS太高会导致系统挂掉;基于这种心理会想着尽量的降低系统的请求量,甚至有人会将很多处理放置到服务中来处理,这样外部发一起请求,服务就把所有的业 ...
- 小米手机无法打开程序报错Unable to instantiate application com.android.tools.fd.runtime.BootstrapApplication的解决办法
打开studio的setting 然后 Preferences -> Build, Execution, Deployment -> Instant Run -> Enable In ...
- [COJ0985]WZJ的数据结构(负十五)
[COJ0985]WZJ的数据结构(负十五) 试题描述 CHX有一个问题想问问大家.给你一个长度为N的数列A,请你找到两个位置L,R,使得A[L].A[L+1].…….A[R]中没有重复的数,输出R- ...
- 学号160809224姓名黄家帅c语言程序设计实验2 选择结构程序设计
实验2-1 输入3个数,并按由大到小的顺序输出. 实验要求: 编写一个C程序,输入3个数,并按由大到小的顺序输出. 源码: #include <stdio.h>void main(){ i ...
- hdu1536&&hdu3023 SG函数模板及其运用
S-Nim Time Limit: 1000MS Memory Limit: 32768KB 64bit IO Format: %I64d & %I64u Submit Status ...
- python的变量作用域问题
偶然掉进了一个坑里.仔细分析了下原因.原来是变量作用域的问题.简单抽象如下: id=1 #许多行代码 [id for id in range(10)] #许多行代码 if id!=1: #做一些事情 ...