前言:
当前朋友们对“tcpip编程”大概比较珍视,朋友们都想要了解一些“tcpip编程”的相关资讯。那么小编也在网上网罗了一些对于“tcpip编程””的相关文章,希望朋友们能喜欢,同学们快快来学习一下吧!网际协议 IP和TCP是 TCP/IP 体系中两个最主要的协议之一。
IP地址与数据包:
IP层就是把数据分组从一个主机跨越千山万水搬运到另外一主机, 并且这搬运服务一点都不可靠, 丢包、重复、失序可以说是家常便饭。
TCP 在两个主机的应用(进程)之间通过失败重传来实现可靠性的传输。
TCP是两个进程之间的通信, 客户端上可以有很多进程同时访问多个服务器, 服务器上也有多个进程对外提供服务。端口号就是用来区分进程的, 这样IP层发过来的数据包, 到达TCP层以后就可以分发给各个应用程序了。
建立一个TCP连接可是相当的复杂, 客户端的网络程序得先和远端的服务器打个招呼, 然后它再给我打个招呼确认, 我还得再给它确认下。 这还不算完, 我们的招呼中还得各自带上各自的序号, 这将来传输真正的数据时用到。
TCP协议的确很复杂, 我们不能要求每个程序员都去实现建立连接的3次握手(确认客户端、服务端的发信、收信能力),分组交换、失败重传(中间节点的路由可以是随机的,允许失序、重复、丢失,可靠的传输完全由两端点来实现,失败后重传即可,而顺序可以由数据包的序号来确定), 这些应该是属于操作系统内核的部分, 没必要重复开发, 但是对于应用程序来讲, 操作系统抽象出一个socket概念, 让上层应用去编程。
socke就像插座一样, 一个插头插进插座, 建立了连接。 可以理解为 (客户端IP, 客户端Port, 服务器端IP, 服务器端Port), Port就是端口, 通俗点讲就是一个数字而已。这也就是多路复用。
一般来说, 服务器端都是被动访问的, 所以大家需要知道它提供服务的端口号, 要不然怎么连接? 例如80, 443等, 就是所谓知名端口号; 而客户端访问服务器的时候,自己的端口号可以随机生成一个, 只要不和别的应用冲突即可。
客户端socket编程首先需要创建一个socket, 然后向服务器发起连接, 连接上以后就可以发送,接收数据了。
下图就是客户端socket的伪代码:
在上面的伪码中,没有出现客户端的ip和端口, 系统可以自动获得IP, 也可以自动分配端口。 还有, 看到那个connect 函数没有, 其实就是在和服务器发起三次握手呢。
服务器端要复杂一些, 第一, 服务器是被动的, 所以它启动以后, 需要监听客户端发起的连接, 第二, 服务器要应付很多的客户端发起连接, 所以它一定得各个socket给区分开了, 要不就乱了套了, 伪代码是这个样子的:
listenfd监听创建的socket描述符, bind 声明说我要占用这个端口, 你们都别用了, listen函数才是真正开始监听了。
服务器要区分开各个客户端, 怎么区分呢? 那只有用一个新的socket来表示喽, 后面的操作都是基于connfd 来做的。 还有这个accept 相当于和客户端的connect 一起完成了TCP的三次握手 ! 至于之前的listenfd , 它只起到一个大门的作用了, 意思是说,欢迎敲门, 进门之后我将为你生成一个独一无二的socket描述符!
不过似乎有个漏洞,一开始说socket指的是 (IP, Port), 现在已经有了一个listenfd 的socket, 端口是80,然后每次客户端发起连接还要创建新的connfd, 因为80端口已经被占用,难道服务器端会为每个连接都创建新的端口吗?
其实新创建的connfd 并没有使用新的端口号,也是用的80, 可以这么理解,这个socket描述符指向一个数据结构, 例如 listenfd 指向的结构是这样的:”
而一旦accept 新的连接, 新的connfd 就会生成,像下面的表格, 就生成了两个connfd , 它们俩服务器端的ip和port都是相同的, 但是客户端的IP和Port是不同的, 自然就可以区分开来了。
其实这个四元组还不太准确, 因为说了半天,都是TCP协议的socket,UDP可以实现无连接的运输层协议, 也有socket,所以更准确的定义的话,还得加上协议这一项, 变成五元组(协议, 客户端IP, 客户端Port, 服务器端IP, 服务器端Port)。
参考:;mid=2665513387&idx=1&sn=99665948d0b968cf15c5e7a01ffe166c&chksm=80d679e8b7a1f0febad077b57e8ad73bfb4b08de74814c45e1b1bd61ab4017b5041942403afb&scene=21#wechat_redirect
标签: #tcpip编程