网络编程tcp(代码片段)

wangtenghui wangtenghui     2022-12-14     726

关键词:

一、TCP协议

1. TCP协议的特点

    1.TCP是面向连接的运输层协议。这就意味着,在使用该协议之前,必须建立TCP连接。在传输数据完毕后,必须释放已经建立的TCP连接。
    
    2.每一条TCP连接只能有两个端点,每一条TCP连接只能是点对点的(一对一)。
    
    3.TCP提供可靠交付的服务。通过TCP连接传送的数据,无差错、不丢失、不重复、并且按序到达。
   
    4.TCP提供全双工通信。TCP允许通信双方的应用进程在任何时候都能发送数据。
        TCP连接的两端都设有发送缓存和接收缓存,用来临时存放双向通信的数据。
        在发送时,应用程序在把数据传送给TCP的缓存后,就可以做自己的事,而TCP在合适的时候把数据发出去。
        在接收时,TCP把收到的数据放入缓存,上层的应用进程在合适的时候读取缓存中的数据。
    
    5.面向字节流。虽然应用程序和TCP的交互试一次一个数据块(注意:大小是不等的),
        但TCP把应用程序交下来的数据仅仅看成是一连串的无结构的字节流。TCP并不知道所传送的字节流的含义。

2.三次握手、四次挥手

技术图片

3.代码实现

3.1 使用TCP协议实现简单通信
# 客户端:
import socket

client = socket.socket()
client.connect((‘127.0.0.1‘, 8080))
client.send(b"this is client!")
data = client.recv(1024)
print(data)
client.close()

# 服务端:
import socket

server = socket.socket()  # 实例化sever对象-->买手机
server.bind((‘127.0.0.1‘, 8080))  # 绑定ip和端口-->手机卡
server.listen(5)  # 监听 -->打开手机
conn, addr = server.accept()  # 等待建立连接
data = conn.recv(1024)  # 接收数据 --> 打电话
print(data)
conn.send(b"received data!!")
conn.close()  # 关闭连接-->挂电话
server.close()  # 关闭服务器 -->关机
3.2 使用TCP协议实现通信循环
# 客户端:
import socket

client = socket.socket()
client.connect((‘127.0.0.1‘, 8080))
while True:
    msg = input(">>>")
    if msg == ‘q‘:
        break
    client.send(msg.encode(‘utf-8‘))
    data = client.recv(1024)
    print(data)
client.close()

# 服务端
import socket

server = socket.socket()  # 实例化sever对象-->买手机
server.bind((‘127.0.0.1‘, 8080))  # 绑定ip和端口-->手机卡
server.listen(5)  # 监听 -->打开手机
conn, addr = server.accept()  # 等待建立连接
while True:
    try:
        data = conn.recv(1024)  # 接收数据 --> 打电话
        print(data)
        conn.send(b"received data!!")
    except ConnectionResetError:
        break
conn.close()  # 关闭连接-->挂电话
server.close()  # 关闭服务器 -->关机
3.3 使用TCP协议实现链接循环
# 客户端
import socket

client = socket.socket()
client.connect((‘127.0.0.1‘, 8080))
while True:
    msg = input(">>>")
    if msg == ‘q‘:
        break
    client.send(msg.encode(‘utf-8‘))
    data = client.recv(1024)
    print(data)
client.close()

# 服务端
import socket

server = socket.socket()  # 实例化sever对象-->买手机
server.bind((‘127.0.0.1‘, 8080))  # 绑定ip和端口-->手机卡
server.listen(5)  # 监听 -->打开手机  (半连接池)
while True:
    conn, addr = server.accept()  # 等待建立连接
    while True:
        try:
            data = conn.recv(1024)  # 接收数据 --> 打电话
            print(data.decode(‘utf-8‘))
            conn.send(b"received data!!")
        except ConnectionResetError:
            break
    conn.close()  # 关闭连接-->挂电话
server.close()  # 关闭服务器 -->关机
3.4 使用TCP协议实现粘包问题
# 客户端
import socket
import struct
import json

client = socket.socket()
client.connect((‘127.0.0.1‘, 8090))
while True:
    msg = input(">>>").encode(‘utf-8‘)
    if len(msg) == 0:
        continue
    client.send(msg)
    header = client.recv(4)
    # 对头进行解包,获取真实数据的长度
    head_len = struct.unpack(‘i‘, header)[0]
    head_dic = json.loads(client.recv(head_len).decode(‘utf-8‘))
    print(head_dic)
    # 对需要接收的数据进行循环接收
    total_size = head_dic[‘len‘]
    recv_size = 0
    res = b‘‘
    while recv_size < total_size:
        data = client.recv(1024)
        res += data
        recv_size += len(data)
    print(res.decode("gbk"))

# 服务端
import socket
import subprocess
import struct
import json

server = socket.socket()  # 实例化sever对象-->买手机
server.bind((‘127.0.0.1‘, 8090))  # 绑定ip和端口-->手机卡
server.listen(5)  # 监听 -->打开手机  (半连接池)
while True:
    conn, addr = server.accept()  # 等待建立连接
    while True:
        try:
            data = conn.recv(1024).decode(‘utf-8‘)  # 接收数据 --> 打电话
            if len(data) == 0: break  # 针对mac和Linux,客户端异常断开反复收空的情况

            # 生成一个能够读取输出、错误流的对象
            obj = subprocess.Popen(data, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            stdout = obj.stdout.read()  # 获得输出流
            stderr = obj.stderr.read()  # 获取错误流

            # 打印输出流+输入流的长度
            print(len(stdout+stderr))
            # 制作一个文件头
            header_dic = 
                ‘filename‘: ‘cls.avi‘,
                ‘len‘: len(stderr+stdout)  # 错误流 或者 输出流 的长度
            

            # 序列化文件头字典,得到文件头的二进制文件
            header_bytes = json.dumps(header_dic).encode(‘utf-8‘)

            # 制作报头
            header = struct.pack(‘i‘, len(header_bytes))  # 将要发送给客户端的数据打包成固定4个字节
            conn.send(header)
            conn.send(header_bytes)
            conn.send(stdout+stderr)

        except ConnectionResetError:
            break
    conn.close()  # 关闭连接-->挂电话

server.close()  # 关闭服务器 -->关机
3.5 解决粘包问题用到的 struct
1.说明
    struct模块中最重要的三个函数是pack(), unpack(), calcsize()
    pack(fmt, v1, v2, ...)    按照给定的格式(fmt),把数据封装成字符串(实际上是类似于c结构体的字节流)
    unpack(fmt, string)       按照给定的格式(fmt)解析字节流string,返回解析出来的tuple
    calcsize(fmt)             计算给定的格式(fmt)占用多少字节的内存
    
    struct中支持的格式如下表:
    网址 : https://www.cnblogs.com/gala/archive/2011/09/22/2184801.html


2.代码实现(例子)
import struct
data = ‘datafa‘
# 服务端
res = struct.pack(‘i‘, len(data))
print(res)  # b‘\\x06\\x00\\x00\\x00‘
print(len(res))  # 4
3.6 解决粘包问题用到的 subprocess
1.说明
subprocess 模块允许你生成新的进程,连接它们的输入、输出、错误管道,并且获取它们的返回码。

class subprocess.Popen(
    args, bufsize=-1, executable=None,
    stdin=None, stdout=None, stderr=None, preexec_fn=None,
    close_fds=True, shell=False, cwd=None, env=None, 
    universal_newlines=None, startupinfo=None, creationflags=0,
    restore_signals=True, start_new_session=False, 
    pass_fds=(), *, encoding=None, errors=None, text=None)


2.代码实现(例子):
cmd = r‘dir file_list‘
obj = subprocess.Popen(
    cmd,
    shell=True,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,
)

stdout = obj.stdout.read()  # 来接住stdout流
print(‘stdout‘, stdout.decode(‘gbk‘))  # 打印进程列表

stderr = obj.stderr.read()
print(‘stderr‘, stderr.decode(‘gbk‘))

# 当上面的命令出错时,接收错误流
# stderr ‘tasklist1‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。
# stdout 和 stderr同时存在的时候,有一个接收到了数据另一个就不会停止等待

二、UDP协议

1. UDP协议的特点

1.UDP是无连接的,即发送数据之前不需要建立连接(发送数据结束时也没有连接可释放),因此减少了开销和发送数据之前的时延。
    
2.UDP使用尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的连接状态表。

3.UDP是面向报文的。发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付IP层。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。

4.UDP没有拥塞控制,因此网络出现的拥塞不会使源主机的发送速率降低。

5.UDP支持一对一,一对多,多对一和多对多的交互通信。

6.UDP的首部开销小,只有8个字节,比TCP的20个字节的首部要短。

2. 代码实现

2.1 使用UDP协议实现简单通信
# 客户端
import socket

client = socket.socket(type=socket.SOCK_DGRAM)
data = b‘this is client‘
server_addr = (‘127.0.0.1‘, 8080)

client.sendto(data, server_addr)
data1, addr1 = client.recvfrom(1024)

print(addr1) 
print(data1) 
# (‘127.0.0.1‘, 8080)
# b‘THIS IS CLIENT‘

# 服务端
import socket

server = socket.socket(type=socket.SOCK_DGRAM)  # udp协议
server.bind((‘127.0.0.1‘, 8080))

while True:
    data, addr = server.recvfrom(1024)
    print(data)
    data = data.decode(‘utf-8‘)
    data = data.upper()

    server.sendto(data.encode(‘utf-8‘), addr)
    
# b‘this is client‘
2.2 使用UDP协议实现极简版QQ
# 客户端
import socket

client = socket.socket(type=socket.SOCK_DGRAM)
server_addr = (‘127.0.0.1‘, 8080)

while True:
    data = input(">>>:").strip()
    client.sendto(data.encode(‘utf-8‘), server_addr)

    msg, addr = client.recvfrom(1024)
    print(msg.decode(‘utf-8‘))

# 服务端
import socket

server = socket.socket(type=socket.SOCK_DGRAM)
server.bind((‘127.0.0.1‘, 8080))

while True:
    data, addr = server.recvfrom(1024)
    print(addr)
    print(data.decode(‘utf-8‘))

    re_msg = input(">>>:")
    server.sendto(re_msg.encode(‘utf-8‘), addr)
2.3 socketServer模块可以使TCP通信达到并发效果
# 客户端
import socket

client = socket.socket()
client.connect((‘127.0.0.1‘, 8080))

while True:
    msg = input(">>>:")
    client.send(msg.encode(‘utf-8‘))

    data = client.recv(1024)
    print(data.decode(‘utf-8‘))

# 服务端
import socketserver

server_addr = (‘127.0.0.1‘, 8080)

class MySock(socketserver.BaseRequestHandler):
    def handle(self):
        # 通信循环
        while True:
            data = self.request.recv(1024)  # 接收数据
            print(data.decode(‘utf-8‘))
            re_msg = input(">>>:")
            self.request.send(re_msg.encode(‘utf-8‘))

if __name__ == ‘__main__‘:
    server = socketserver.ThreadingTCPServer(server_addr, MySock)
    server.serve_forever()

golanggo语言网络编程tcp实现通信(代码片段)

这里写目录标题TCP客户端(client)TCP服务端(server)TCP客户端(client)packagemainimport( "bufio" "fmt" "net" "os" "strings")/*一个TCP客户端进行TCP 查看详情

网络编程——tcp协议socket(代码片段)

TCP协议与socket套接字一、TCP协议1、可靠传输,TCP数据包没有长度限制,理论上可以无限长,但是为了保证网络的效率,通常TCP数据包的长度不会超过IP数据包的长度,以确保单个TCP数据包不必再分割。2.(1)三次握手建链接(2... 查看详情

linux:tcpsocket编程(代码实战)(代码片段)

....4发送数据接口1.2.5接收数据接口1.3三次握手的简单验证2.代码实战2.1单进程版本的TCP代码2.2多进程版本的TCP代码2.3多线程版本的TCP代码1.TCP的Socket编程1.1TCP的编程流程和UDP编程一样 查看详情

网络1-28(代码片段)

...p能不能一次连接多次请求,不等后端返回5.讲讲怎么理解网络编程6.网络编程过程,建立一个socket连接步骤过程7.tcp协议过程8.TCP有哪些状态?9.TCP的LISTEN状态是什么?10.TCP的CLOSE_WAIT状态是什么?11.TCP的TIME_WAIT状态存在的理由 查看详情

026.3网络编程tcp聊天(代码片段)

分为客户端和服务端,分别进行收发操作##########################################################################客户端:###思路:1、建立tcp客户端服务   1.1因为是面向连接,必须有连接才有通信   1.2在创建客户端时,就... 查看详情

tcp网络编程双向多次通讯(代码片段)

客户端packagetcptx;importjava.io.BufferedReader;importjava.io.IOException;importjava.io.InputStreamReader;importjava.io.OutputStreamWriter;importjava.net.InetAddress;importjava.net.Socket;importjava.net. 查看详情

linux网络编程必学!——linux_网络编程_tcp(代码片段)

文章目录1.TCP概念2.TCP编程接口2.1listen()2.2accept()2.3connect()2.4send()/recv()3.三次握手4.四次挥手5多进程版本TCP6多线程版本TCP7TCPvsUDP1.TCP概念传输控制协议(TCP,TransmissionControlProtocol)是一种面向连接的、可靠的、基于字节... 查看详情

网络linuxlinux网络编程-tcp,udp套接字编程及代码示范(代码片段)

这里写目录标题UDP类UDP服务端单执行流UDP客户端TCP类TCP单执行流服务器TCP客户端TCP多执行流(线程)TCP多执行流(进程)本文我们分为TCP和UDP协议网络程序的编写:他们的区别如下:项目特点UDP用户数据报协议,无需连接&#... 查看详情

tcp编程(代码片段)

转自:https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001386832511628f1fe2c65534a46aa86b8e654b6d3567c000Socket是网络编程的一个抽象概念。通常我们用一个Socket表示“打开了一个网络链接”,而打开一个Socket需要知道目标 查看详情

181112网络通信tcp(代码片段)

tec客户端的接受代码importsocketdefmain():#1.创建tcp的套接字tcp_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#2.链接服务器#tcp_socket.connect(("192.168.33.11",7890))server_ip=input("请输入要链接的服务器的ip:")server_port= 查看详情

qt学习_网络编程_tcp通信聊天(代码片段)

网络编程TCP通信1.用到的类QTcpServer公共函数:void close()QString errorString()constbool isListening()constbool listen(constQHostAddress&address=QHostAddress::Any,quint16port=0)QHostAddre 查看详情

网络编程——tcp协议和通信(代码片段)

第1章 TCP通信TCP通信同UDP通信一样,都能实现两台计算机之间的通信,通信的两端都需要创建socket对象。区别在于,UDP中只有发送端和接收端,不区分客户端与服务器端,计算机之间可以任意地发送数据。而TCP通信是严格区... 查看详情

java网络编程编程之tcp编程和udp编程(代码片段)

网络编程基础1.TCP编程1.1网络相关基础概念1.2TCP协议介绍1.3TCP编程案例2.UDP编程2.1UDP协议介绍2.2UDP编程案例1.TCP编程1.1网络相关基础概念我们在学习网络编程前先来复习一下IP地址端口号协议,套接字的相关概念。IP地址:用来... 查看详情

51.使用tcp协议检测网络性能(代码片段)

TCP协议通过滑动窗口方式,可以充分利用网络性能传输数据。所以,利用TCP传输机制,可以检测网络性能。netwox工具提供了相关模块来实现该功能,可以使用编号为155的模块建立TCP服务器,使用编号为156的模... 查看详情

计算机网络-tcp(代码片段)

TCP的全称是传输控制协议(TransmissionControlProtocol)[RFC793]TCP提供面向连接的服务。在传送数据之前必须先建立连接,数据传送结束后要释放连接。TCP不提供广播或多播服务。由于TCP要提供可靠的、面向连接的服务,因此不可避免... 查看详情

python网络编程(通过tcp或者udp协议通信)(代码片段)

1、基于tcp协议传送文件:  客户端:importsocketimportosimportjsonimportstructclient=socket.socket()client.connect((‘127.0.0.1‘,8080))#文件大小file_size=os.path.getsize(r‘F:\老男孩Python7期\day32\视频\02TCP发送大文件.mp4‘)#文件名字file 查看详情

tcp的网络编程基础(代码片段)

        服务器建立ServerSocket对象ServerSocket对象负责等待客户端请求建立套接字连接,类似邮局某个窗口中的业务员。也就是说,服务器必须事先建立一个等待客户请求建立套接字的连接的ServerSocket... 查看详情

linux网络编程——tcp和udp通信(代码片段)

TCP协议流程图、TCP建立即时聊天TCP即时聊天升级:服务器在客户端断开后不断开,客户端可以多次重连服务器进行即时聊天UDP协议流程图、UDP建立即时连接如果在已经处于ESTABLISHED状态下的socket(一般由端口号和标志符区分)需调... 查看详情