socket编程及tcp、UDP协议

1、TCP UDP区别:

  TCP有点:可靠,稳定,TCP可靠提现在TCP在传递数据之前,会有三次握手来建立连接,而且在数据传输时,有确认、窗口、重传、拥塞控制机制,在数据传完后,还会断开连接来节约系统资源。

  TCP缺点:慢、效率低、占用系统资源高,易呗攻击,TCP在传递数据之前,要先建立连接,这会消耗时间,而且在数据传输时,确认机制、重传机制、拥塞机制等都会消耗大量的时间,而且要再每台设备上维护所有的传输连接,事实上,每个连接都会占用系统的CPU,内存等硬件资源,而且,因为TCP有确认机制,这些也导致TCP容易被人利用,实现DOS、DDOS、CC等攻击。

  UDP优点:快,比TCP稍安全,没有TCP的握手、确认、窗口、重传、拥塞控制等机制,UDP是一个无状态的传输协议,所以在传递数据时非常快,没有TCP的这些机制,UDP较TCP被攻击者利用的漏洞就要少一点。但UDP也是无法避免攻击的,比如UDP Flood攻击。。。

  UDP缺点:不可靠,不稳定 因为UDP没有TCP那些可靠的机制,在数据传递时,如果网络质量不好,就会容易丢包。

  TCP UDP
是否连接 面向连接(TCP三次握手) 面向非连接
传输可靠性 可靠 不可靠
应用场合 少量数据,安全(浏览器HTTP、FTP Outlook、SMTP Putty) 传输大量数据(QQ语音、视频、直播等)
速度

2、TCP三次握手和四次挥手

  三次握手:

初始状态:客户端A和服务器B均处于CLOSED状态,然后服务器B创建socket,调用监听接口使得服务器处于LISTEN状态,等待客户端连接。(后续内容用A,B简称代替)

A首先向B发起连接,这时TCP头部中的SYN标识位值为1,然后选定一个初始序号seq=x(一般是随机的),消息发送后,A进入SYN_SENT状态,SYN=1的报文段不能携带数据,但要消耗一个序号。

B收到A的连接请求后,同意建立连接,向A发送确认数据,这时TCP头部中的SYN和ACK标识位值均为1,确认序号为ack=x+1,然后选定自己的初始序号seq=y(一般是随机的),确认消息发送后,B进入SYN_RCVD状态,与连接消息一样,这条消息也不能携带数据,同时消耗一个序号。

A收到B的确认消息后,需要给B回复确认数据,这时TCP头部中的ACK标识位值为1,确认序号是ack=y+1,自己的序号在连接请求的序号上加1,也就是seq=x+1,此时A进入ESTABLISHED状态,当B收到A的确认回复后,B也进入ESTABLISHED状态,至此TCP成功建立连接,A和B之间就可以通过这个连接互相发送数据了。

  四次挥手:

  

初始状态:客户端A和服务器B之间已经建立了TCP连接,并且数据发送完成,打算断开连接,此时客户端A和服务器B是等价的,双方都可以发送断开请求,下面以客户端A主动发起断开请求为例。(后续内容用A,B简称代替)

A首先向B发送断开连接消息,这时TCP头部中的FIN标识位值为1,序号是seq=m,m为A前面正常发送数据最后一个字节序号加1得到的,消息发送后A进入FNI_WAIT_1状态,FIN=1的报文段不能携带数据,但要消耗一个序号。

B收到A的断开连接请求需要发出确认消息,这时TCP头部中的ACK标识位值为1,确认号为ack=m+1,而自己的序号为seq=n,n为B前面正常发送数据最后一个字节序号加1得到的,然后B进入CLOSE_WAIT状态,此时就关闭了A到B的连接,A无法再给B发数据,但是B仍然可以给A发数据(此处存疑),同时B端通知上方应用层,处理完成后被动关闭连接。然后A收到B的确认信息后,就进入了FIN_WAIT_2状态。

B端应用层处理完数据后,通知关闭连接,B向A发送关闭连接的消息,这时TCP头部中的FIN和ACK标识位值均为1,确认号ack=m+1,自己的序号为seq=k,(B发出确认消息后有发送了一段数据,此处存疑),消息发送后B进入LACK_ACK状态。

A收到B的断开连接的消息后,需要发送确认消息,这是这时TCP头部中的ACK标识位值为1,确认号ack=k+1,序号为m+1(因为A向B发送断开连接的消息时消耗了一个消息号),然后A进入TIME_WAIT状态,若等待时间经过2MSL后,没有收到B的重传请求,则表明B收到了自己的确认,A进入CLOSED状态,B收到A的确认消息后则直接进入CLOSED状态。至此TCP成功断开连接。

3、socket理解:

socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口;

#!/usr/bin/python
# -*- coding:utf-8 -*-
import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #买手机
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind(('127.0.0.1',8080)) #插电话卡
phone.listen(5) #开机,backlog

while True: #链接循环
    print('starting....')
    conn,addr=phone.accept() #接电话
    print('cliet addr',addr)
    while True: #与conn的通信循环
        try:#针对windows平台下客户端断开链接
            client_msg=conn.recv(1024) #收消息
            if not client_msg:break #针对linux系统平台下客户端断开链接
            print('client msg: %s' %client_msg)
            conn.send(client_msg.upper()) #发消息
        except Exception:
            break
    conn.close()
phone.close()
View Code

猜你喜欢

转载自www.cnblogs.com/wangkc/p/10868811.html