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函数的工作流程。
  1. 阻塞模式下的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编程的更多相关文章

  1. ios开发网络知识 TCP,IP,HTTP,SOCKET区别和联系

    TCP,IP,HTTP,SOCKET区别和联系 网络由下往上分为:        对应 物理层-- 数据链路层-- 网络层--                       IP协议 传输层--     ...

  2. 网络编程——基于TCP协议的Socket编程,基于UDP协议的Socket编程

    Socket编程 目前较为流行的网络编程模型是客户机/服务器通信模式 客户进程向服务器进程发出要求某种服务的请求,服务器进程响应该请求.如图所示,通常,一个服务器进程会同时为多个客户端进程服务,图中服 ...

  3. TCP/IP协议网络编程以及UDP和TCP之传输协议

    1.什么是TCP/IP协议? 网络编程协议有很多,目前应用最广泛的是TCP/IP协议(Transmission Control Protocal/Internet Protoal 传输控制协议/英特网 ...

  4. 网络协议HTTP、TCP/IP、Socket

    网络协议HTTP.TCP/IP.Socket 网络七层由下往上分别为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层.  其中物理层.数据链路层和网络层通常被称作媒体层,是网络工程师所研究的 ...

  5. Linux内核 TCP/IP、Socket参数调优

    Linux内核 TCP/IP.Socket参数调优 2014-06-06  Harrison....   阅 9611  转 165 转藏到我的图书馆   微信分享:   Doc1: /proc/sy ...

  6. 基于TCP(面向连接)的Socket编程

    基于TCP(面向连接)的Socket编程 一.客户端: 1.打开一个套接字(Socket); 2.发起连接请求(connect); 3.如果连接成功,则进行数据交换(read.write.send.r ...

  7. TCP/IP、SOCKET、HTTP之间的联系与区别

    主要内容: 1.网络的七层协议 2.TCP/IP.SOCKET.HTTP简介 3.TCP连接.HTTP连接.Socket连接的区别 一.网络的七层协议 网络七层由下往上分别为物理层.数据链路层.网络层 ...

  8. 基于TCP/UDP的socket编程

    基于TCP(面向连接)的socket编程服务器端顺序: 1. 创建套接字(socket) 2. 将套接字绑定到一个本地地址和端口上(bind) 3. 将套接字设为监听模式,准备接收客户请求(liste ...

  9. TCP/IP以及Socket聊天室带类库源码分享

    TCP/IP以及Socket聊天室带类库源码分享 最近遇到个设备,需要去和客户的软件做一个网络通信交互,一般的我们的上位机都是作为客户端来和设备通信的,这次要作为服务端来监听客户端,在这个背景下,我查 ...

随机推荐

  1. 深入理解 CSS3 弹性盒布局模型

    Web 应用的样式设计中,布局是非常重要的一部分.布局用来确定页面上不同组件和元素的尺寸和位置.随着响应式用户界面的流行,Web 应用一般都要求适配不同的设备尺寸和浏览器分辨率.响应式用户界面设计中最 ...

  2. CSS3必须要知道的10个顶级命令

    1.边框圆角(Border Radiuas) 这个是我们在平常很常用的吧,以前我在用div圆角的时候,特别特别的痛苦,不管是用CSS来画圆角,还是用图片来画圆角都不那么容易,但是现在好了,在CSS3中 ...

  3. spring 控制事务

    <!-- 对数据源进行事务管理 -->        <bean id="transactionManager"         class="org. ...

  4. HDU 5023 A Corrupt Mayor's Performance Art(线段树区间更新)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5023 解题报告:一面墙长度为n,有N个单元,每个单元编号从1到n,墙的初始的颜色是2,一共有30种颜色 ...

  5. 揭露QPS增高后的秘密

    导读 很多人在实际的开发中害怕系统的QPS增高,因为觉得QPS太高会导致系统挂掉;基于这种心理会想着尽量的降低系统的请求量,甚至有人会将很多处理放置到服务中来处理,这样外部发一起请求,服务就把所有的业 ...

  6. 小米手机无法打开程序报错Unable to instantiate application com.android.tools.fd.runtime.BootstrapApplication的解决办法

    打开studio的setting 然后 Preferences -> Build, Execution, Deployment -> Instant Run -> Enable In ...

  7. [COJ0985]WZJ的数据结构(负十五)

    [COJ0985]WZJ的数据结构(负十五) 试题描述 CHX有一个问题想问问大家.给你一个长度为N的数列A,请你找到两个位置L,R,使得A[L].A[L+1].…….A[R]中没有重复的数,输出R- ...

  8. 学号160809224姓名黄家帅c语言程序设计实验2 选择结构程序设计

    实验2-1 输入3个数,并按由大到小的顺序输出. 实验要求: 编写一个C程序,输入3个数,并按由大到小的顺序输出. 源码: #include <stdio.h>void main(){ i ...

  9. hdu1536&&hdu3023 SG函数模板及其运用

    S-Nim Time Limit: 1000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & %I64u Submit Status ...

  10. python的变量作用域问题

    偶然掉进了一个坑里.仔细分析了下原因.原来是变量作用域的问题.简单抽象如下: id=1 #许多行代码 [id for id in range(10)] #许多行代码 if id!=1: #做一些事情 ...