tcp实现网络通信(服务端及客户端)

tcp实现网络通信


tcp网络_发送与接收

    什么是tcp ?
        tcp 传输控制协议 (Transmission Control Protocol,缩写为 TCP)是一种面向连接的、可靠的、基于字节流的通信协议
        1.面向连接:
            tcp是面向连接的,先建立连接在进行网络传输  比如打电话
            udp是不需要连接的,类似于写信,发短信的形式

        2.可靠的,tcp可通过一系列的机制来保证数据的安全、质量传输
            面向连接机制
            发送应答机制
            超时重传机制
            ...
        3.基于字节流的
            udp创建的是基于字节串的,udp创建的socket.SOCK_DGRAM是基于数据报的通信协议
                数据报也称一个独立的数据单元

            tcp创建的socket.SOCK_STREAM 是基于字节流的

    tcp通信的三个步骤
        面向连接:
            1,建立连接
            2.发送与接收数据
            3.关闭连接

    tcp的特点
        1.面向连接:
            1.先连接,在通信
            2.tcp面向连接是一对一的连接,意思是当你创建一个新的socket套接字时,服务端也会给你一个socket进行对接
            udp可以一对多,也可一对地,编写广播通信程序,则使用udp通信

        2.可靠的,tcp可通过一系列的机制来保证数据的安全、质量传输
            1.发送应答机制
            2.超时重传机制
            3.错误效验机制
            4.流量控制 阻塞管理机制

2.udp与tcp的不同
    1.TCP与UDP的不同点
        面向连接
        有序数据传输
        重发丢失的数据包
        舍弃重复的数据包
        无差错的数据传输
        阻塞/流量控制

    2.tcp与udp的应用场景
        udp:
            1.面向无连接的,可一对一或一对多,相对tcp速度更快,实时性更好,耗资源更少,但稳定性、可靠性比tcp差 
            2.多点通信,比如广播通信 
            3.当对网络通讯质量要求不高的时候,要求网络通讯速度能尽量的快,更实时,使用UDP ,比如QQ语音,QQ视频
          tcp:
            1.面向连接,且一对一,比udp更稳定,可靠,适合通信质量要求较高的场景
            2.http传输,文件传输,smtp等等,目前大部分的传输都会基于tcp协议传输
            3.即使通信: qq

    3.UDP与TCP的通信模型
        udp:
            面向无连接,好比发短信,,没有严格的服务端与客户端之分
        tcp:
            面向连接,好比打电话,有严格的服务端与客户端之分
  1. TCP客户端实现流程
    1. 创建一个tcp 的socket客户端对象
    2. 与服务端建立连接
    3. 发送与接收数据
    4. 关闭连接,关闭socket对象
    tcp_socket.close()
    参考代码:
#tcp网络传输-客户端流程
import socket

#1.创建socket套接字对象
tcp_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#准备目标主机ip地址
addrress = ("192.168.79.133",9996)
#连接服务器
tcp_socket.connect(addrress)
#准备发送数据
data = input("请输入要发送的数据:")
tcp_socket.send(data.encode("utf-8"))

#接收回传数据
recv_data = tcp_socket.recv(1024)
new_recv_data = recv_data.decode("gbk")
print("回传数据为:",new_recv_data)

tcp_socket.close()
  1. tcp服务端创建流程
    1. 创建一个服务端的tcp socket(server_socket) , 用于监听客户端的请求的
    2. 绑定端口 bind()
    3. 服务端的server_socket开启监听,由主动模式变为被动模式 listen()
    4. 等待客户端的连接请求,一有请求,则立即接收,且创建一个新的 socket,与当前请求的客户端通信 accept()
    5. 使用新创建的socket与客户端通信
    6. 关闭新创建的与客户端通信的socket, 假如该socket关闭,则结束与客户端通信
    7. 关闭用于监听的socket(server_socket),该socket关闭,则不再接收新的客户端请求
    参考代码:
#tcp网络传输-服务端流程
import socket

def main():
    # 创建socket
    tcp_cliend_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    #端口复用
    tcp_cliend_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)

    #本地信息及端口绑定
    local_addr = ('192.168.78.101',8888)
    tcp_cliend_socket.bind(local_addr)

    #.将socket主动变成被动,开启监听
    tcp_cliend_socket.listen(2)#5表示最大的等待数
    #可循环接收多个客户端的信息
    while True:
        # 这里。accept接收的是新的socket对象,不是之前创建的socket,
        # accept返回的是两个值,一个是与客户端连接的socket对象 ,另一个是客户端的地址
        new_socket, cliend_addr = tcp_cliend_socket.accept()
        print("有新的客户端请求,来自",cliend_addr)
        while True:
            #当客户端的socket关闭后,会发送一个长度为0的消息给服务器的socket,且处于阻塞状态
            #4.接收回传的数据信息
            recv_data = new_socket.recv(1024)
            if recv_data:

                print("接收到的数据为",recv_data.decode('utf-8'))

                #发送回传信息
                send_data = "谢谢"
                new_socket.send(send_data.encode('utf-8'))
            else:
                print("客户端已下线")
                break
        new_socket.close()
    #关闭套接字
    tcp_cliend_socket.close()

if __name__ == '__main__':
    main()

TCP注意点

    1.tcp服务端一般情况下都需要绑定,否则客户端找不到这个服务端

    2.tcp客户端一般不绑定,因为是主动连接服务端,所以只要确定好服务端的ip、port等信息就好,本地客户端可以随机

    3.tcp服务端中通过listen可以将socket创建出来的主动套接字变为被动的,这是做tcp服务端时必须要做的

    4.当客户端需要连接服务端时,就需要使用connect进行连接,udp是不需要连接的而是直接发送,但是tcp必须先连接,只有连接成功才能通信

    5.当一个tcp客户端连接服务端时,服务端会有1个新的套接字,这个套接字用来标记这个客户端,单独为这个客户端服务

    6.listen后的套接字是被动套接字,用来接收新的客户端的连接请求的,而accept返回的新套接字是标记这个新客户端的

    7.关闭listen后的套接字意味着被动套接字关闭了,会导致新的客户端不能够连接服务端,但是之前已经连接成功的客户端正常通信。

    8.关闭accept返回的套接字意味着这个客户端已经服务完毕

    9.当客户端的套接字调用close后,服务端会recv解堵塞,并且返回的长度为0,因此服务端可以通过返回数据的长度来区别客户端是否已经下线
        通常这一点用于判断客户端是否已经下线

猜你喜欢

转载自blog.csdn.net/sinat_31907813/article/details/82596160