TCP和UDP的异同(含:TCP/UDP编写的网络聊天程序+TCP传文件)

目录

引言

一、TCP介绍

二、UDP介绍

三、拓展(TCP加强版:SSL)

四、TCP与UDP的比较

五、使用TCP/UDP编写网络聊天程序


引言

因特网为应用程序提供了两个运输层(传输层)协议,即TCPUDP。当我们为因特网创建一个新的应用程序时,我们首先需要考虑的是:选择TCP还是UDP。这两个协议都为调用它们的应用程序提供了不同的服务集合

 

一、TCP介绍

TCP大的服务模型包括:面向连接的服务可靠的数据传输服务以及拥塞控制机制

  • 面向连接的服务:在应用层的数据报文开始流动之前,先进行三次握手建立连接,即TCP让客户和服务器相互交换运输层的控制信息。
  • 可靠的数据传输服务:不同的主机间的不同进程间能够依靠TCP进行无差错按适当顺序交付所有发送的数据。
  • 拥塞控制机制:当发送方和接收方之间的网络出现拥塞时,TCP的拥塞控制机制会抑制发送进程(客户/服务器);TCP拥塞控制机制也试图限制每个TCP连接,使它们达到公平共享网络带宽的目的。

 

二、UDP介绍

UDP是一种不提供不必要(no-frills)服务的轻量级运输协议,它仅提供最小的服务。UDP是无连接的,因此在两个进程通信前没有握手的过程。UDP协议提供一种不可靠数据传输服务,也就是说,当进程将一个报文发送进UDP套接字时,UDP协议并不保证该报文将到达接收进程。不仅如此,到达接收进程的报文也可能是乱序的。

UDP也没有拥塞控制机制,所以UDP的发送端可以用它选定的任何速率向其下层(网络层)注入数据。

 

三、拓展(TCP加强版:SSL)

TCP/UDP都没有提供任何加密机制,因此因特网界提供了一个在应用层上实现的加强版的TCP,叫作:安全套接字层(Secure Sockets Layer, SSL)。

 

四、TCP与UDP的比较

1、连接:TCP面向连接;UDP是无连接的。

2、可靠:TCP提供可靠传输服务:无差错、按序到达;UDP在IP尽力而为服务之上不提供不必要服务,因此不提供可靠传输。

3、实时性:UDP有较好的实时性,效率比TCP高。

4、拥塞控制:TCP有拥塞控制机制;UDP无拥塞控制机制。

5、流量控制:TCP有流量控制;UDP无流量控制。

6、资源:TCP对系统资源要求多;UDP对系统资源要求少。

 

五、使用TCP/UDP编写网络聊天程序

UDP:

# Client.py
import socket
import time, threading
# 创建套接字,参数1:指示了地址簇,IF_INEF指示了底层使用IPv4;
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

def tcplink():
    while True:
        js = input('我:')
        s.sendto(js.encode('utf-8'), ('127.0.0.1', 9994))   

        data = s.recv(1024)
        time.sleep(1)
        if not data or data.decode('utf-8') == 'exit':
            print('Connection closed.')
            break
        print(('东方不败:%s' % data.decode('utf-8'))+ '         ' + time.strftime("%H:%M:%S"))  
    s.close()
t = threading.Thread(target=tcplink, args=())
t.start()
# Server.py
import socket
import time, threading
import os
# 创建了一个socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 监听端口
s.bind(('127.0.0.1', 9994))

print('Waiting for connection...')

while True:
    message, clientAddress = s.recvfrom(2048)
    time.sleep(1)
    if message.decode('utf-8') == 'exit':
            break
    print(message.decode('utf-8'))
    js = input('我:')
    s.sendto(js.encode('utf-8'), clientAddress)

TCP:聊天+传文件(附加进度条)

# TCPClient.py
import socket
import time, threading
import os
import struct
import sys
import json
from processbar import process_bar
buffsize = 1024
# 创建了一个socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 监听端口
s.bind(('127.0.0.1', 9994))
# 调用listen()方法开始监听端口
s.listen(5)
print('Waiting for connection...')

# 接收文件函数
def recvfile(sock):
    # 接收报文的长度
    head_struct = sock.recv(4)
    if head_struct:
        print('等待接收数据:')
    # 解析出报头的字符串大小
    head_len = struct.unpack('i', head_struct)[0]
    #print(head_len)
    # 接收长度为head_len的报头内容信息(包含文件大小,文件名的内容)
    data = sock.recv(head_len)
    head_dir = json.loads(data.decode('utf-8'))
    filesize_b = head_dir['filesize_bytes']
    filename = head_dir['filename']
    # 接收真实的文件内容
    recv_len = 0
    recv_mesg = b''
    old = time.time()
    f = open(filename, 'wb')
    while recv_len < filesize_b:
        percent = recv_len / filesize_b
        process_bar(percent)
        if(filesize_b - recv_len > buffsize):
            recv_mesg = sock.recv(buffsize)
            f.write(recv_mesg)
            recv_len += len(recv_mesg)
        else:
            recv_mesg = sock.recv(filesize_b - recv_len)
            recv_len += len(recv_mesg)
            f.write(recv_mesg)
    print(recv_len, filesize_b)
    now = time.time()
    stamp = int(now - old)
    print('接收成功,总共用时%ds' % stamp)
    f.close()
    
# 对每个连接的客户端所做的处理
def tcplink(sock, addr):
    # print('Accept new connection from %s%s...' % addr)
    # sock.send(b'Welcome!')
    while True:
        data = sock.recv(1024)
        time.sleep(1)
        # 若接收到sendfile则调用接受文件函数,接收成功后进入下一轮
        if(data.decode('utf-8') == 'sendfile'):
            recvfile(sock)
            continue
    
        if not data or data.decode('utf-8') == 'exit':
            break
        print(('西门吹雪:%s' % data.decode('utf-8')) + '         ' + time.strftime("%H:%M:%S"))
        js = input('我:')
        sock.send(js.encode('utf-8'))
        # sock.send(('Hello, %s' % data.decode('utf-8')).encode('utf-8'))
    sock.close()
    print('Connection from %s%s closed.' % addr)

# 接下来服务器通过一个永久循环来接受来自客户端的连接, accept()会等待并返回一个客户端的连接
while True:
    # 接受一个新连接
    sock, addr = s.accept()
    # 创建新线程来处理TCP连接
    t = threading.Thread(target=tcplink, args=(sock, addr))
    t.start()


# TCPClient.py
import socket
import time, threading
import struct
import json
import os
# 创建套接字,参数1:指示了地址簇,IF_INEF指示了底层使用IPv4;参数2:表明创建了一个TCP套接字
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 建立连接
s.connect(('127.0.0.1', 9994))

# 发送文件的函数
def file_process():
    filemesg = input('请输入传送的文件名>>>').strip()
    # 获取文件的大小(字节)
    filesize_bytes = os.path.getsize(filemesg)
    # 发送文件重命名
    filename = 'new' + filemesg 
    dirc = {
        'filename' : filename,
        'filesize_bytes' : filesize_bytes,
    }
    # 将字典转换为字符串
    head_info = json.dumps(dirc) 
    # 将字符串的长度打包
    head_info_len =  struct.pack('i', len(head_info))
    # 发送head_info的长度
    s.send(head_info_len)
    # 发送head_info
    s.send(head_info.encode('utf-8'))
    # 发送真实的文件信息
    with open(filemesg, 'rb') as f:
        data = f.read()
        s.sendall(data)
    print('发送成功')

# 接收消息的函数
def tcplink():
    while True:
        js = input('我:')
        s.send(js.encode('utf-8'))
        # 假如是sendfile则调用发送文件函数,待发送成功后重新进入下一轮
        if(js == 'sendfile'):
            file_process() 
            continue

        data = s.recv(1024)
        time.sleep(1)
        if not data or data.decode('utf-8') == 'exit':
            print('Connection closed.')
            break
        print(('东方不败:%s' % data.decode('utf-8'))+ '         ' + time.strftime("%H:%M:%S"))  
    s.close()

# 创建一个线程用来用于和服务器建立连接
t = threading.Thread(target=tcplink, args=())
t.start()

# processbar.py
# 进度条显示代码
import sys
import time
def process_bar(precent, width = 50):
    use_num = int(precent*width)
    space_num = int(width-use_num)
    precent = precent*100
    print('[%s%s]%d%%' % (use_num*'#', space_num*' ', precent), file=sys.stdout, flush=True, end='\r')

参考博文:

1、https://blog.csdn.net/xiaobangkuaipao/article/details/76793702

2、https://www.cnblogs.com/xiaomayizoe/p/5258754.html

3、https://www.cnblogs.com/HPAHPA/p/7737641.html

 

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值