首页 > 编程语言 >02. TCP编程

02. TCP编程

时间:2023-10-25 19:56:33浏览次数:26  
标签:02 socket 编程 TCP 服务器 接字 连接 客户端

一、什么是TCP协议

  TCP 协议则是建立在 IP 协议之上的。TCP 协议负责在两台计算机之间建立可靠连接,保证数据包按顺序达到。TCP 协议会通过 3 次握手建立可靠连接。然后需要对每个 IP 包进行编号,确保对方按顺序收到,如果包丢了,就自动重发。一个 TCP 报文来了以后,到底是交给那个程序,就需要端口号来区分。每个网络程序都向操作系统申请一个端口号。这样,两个进程在两台计算机之间建立网络连接就需要各自的 IP 地址和各自的端口号。一个进程也可以能同时与多个计算机建立连接,因此它会申请多个端口。

TCP通信

TCP 每次发送一个数据包,对方都要进行确认,保证数据准确到达对象(不需要应用程序来做这件事,操作系统会自动来做);

TCP 通信的过程中,可以想象成这个虚拟的通道正在占用,不允许其它人来发送结束;

TCP 只需要建立一次连接,之后只需要发送数据,而不需要填写对象的 IP 和 PORT;

二、创建TCP服务器

  创建 TCP 服务器的伪代码如下:

import socket                   # 导入socket模块

ss =  socket.socket()           # 创建服务器套接字
ss.bind()                       # 套接字与地址绑定
ss.listen()                     # 监听连接

while True:                     # 监听连接
    cs = ss.accept()            # 接收客户端连接
    while True:                 # 通信循环
        cs.recv()/cs.send()     # 对话(接收/发送)
    cs.close()                  # 关闭客户端套接字

ss.close()                      # 关闭服务器套接字

  所有套接字都是通过使用 socket.socket() 函数来创建的。因为服务器需要占用一个端口并等待客户端的请求,所以它们必须绑定到一个本地地址。特别地,TCP 服务器必须监听(传入)的连接。

  调用 accept() 方法之后,就开启了一个简单的(单线程)服务器,它会等待客户端的连接。默认情况下,accept() 是阻塞的,这意味着指定将被暂停,直到一个连接到达。一旦服务器接收一个连接,就会返回(利用 accept())一个独立的客户端套接字,用来与即将到来的消息交换。当一个传入的请求到达时,服务器会创建一个新的通信接口来直接与客户端进行通信,再次空出主要的端口,以使其接收新的客户端连接。

  一旦创建了临时套接字,通信就可以开始,通过使用这个新的套接字,客户端与服务器就可以开始参与发送和接收的对话中,直达连接终止。当一方关闭连接或者向对方发送一个空字符串时,通常就会关闭连接。

from socket import socket
from socket import AF_INET, SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR
from time import ctime

HOST = "127.0.0.1"
PORT = 8080
ADDRESS = (HOST, PORT)

tcp_server = socket(AF_INET, SOCK_STREAM)               # 创建服务器套接字
tcp_server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)      # 解决端口占用问题
tcp_server.bind(ADDRESS)                                # 套接字与地址绑定
tcp_server.listen(5)                                    # 监听连接,最大挂起连接数为5

while True:                                             # 监听连接
    print("waiting for connection...")
    connection, address = tcp_server.accept()           # 接收客户端连接
    print("...connection from: ", address)

    while True:                                         # 通信循环
        try:
            recv_data = connection.recv(1024)           # 服务端接收消息,单次最大接收为1024个字节
            # 在Linux系统中,一旦data收到空,意味着是一种异常的行为:客户端非法断开连接
            if not recv_data:                           # 适用于Linux系统
                break
            print(f"收到客户端【{address}】发送的数据:{recv_data.decode('utf-8')}")
            connection.send(f"【{ctime()}】 {recv_data.decode('utf-8')}".encode("utf-8"))  # 服务端发送消息
        except ConnectionResetError:                    # 适用于Windows系统
            break

    connection.close()                                  # 关闭连接

tcp_server.close()                                      # 关闭服务器套接字

  在代码中,一个客户端连接关闭之后,服务器就会等到另一个客户端连接。

三、创建TCP客户端

  创建 TCP 服务器的伪代码如下:

import socket               # 导入socket模块

cs =  socket.socket()       # 创建客户端套接字
cs.connect()                # 尝试连接服务器

while True:                 # 通信循环
    cs.send()/cs.recv()     # 对话(发送/接收)

cs.close()                  # 关闭客户端套接字

  所有套接字都是利用 socket.socket() 创建的。然而,一旦客户端拥有了一个套接字,它就可以利用套接字的 connect() 方法直接创建一个到服务器的连接。当连接建立之后,它就可以直接参与到与服务器的一个对话中。最后,一旦客户端完成了它的事务,它就可以关闭套接字,终止此次连接。

from socket import socket
from socket import AF_INET, SOCK_STREAM

HOST = "127.0.0.1"
PORT = 8080
ADDRESS = (HOST, PORT)

tcp_client = socket(AF_INET, SOCK_STREAM)               # 创建客户端套接字
tcp_client.connect(ADDRESS)                             # 尝试连接服务器

while True:                                             # 通信循环
    send_data = input("请输入要发送的数据: ").strip()
    if not send_data:                                   # 按空格、回车等键结束连接
        break
    tcp_client.send(send_data.encode("utf-8"))          # 客户端发送数据,不允许发送空数据

    recv_data = tcp_client.recv(1024)                   # 客户端接收数据,单次最大接收为1024个字节
    if not recv_data:
        break
    print(f"收到服务端【{ADDRESS}】返回的数据:{recv_data.decode('utf-8')}")

tcp_client.close()                                      # 关闭客户端套接字

四、执行TCP服务器和客户端

  如果先运行客户端,那么将无法进行任何连接,因为没有服务器等待接受请求。服务器可以视为一个被动伙伴,因为必须首先建立自己,然后被动的等待连接。另一方面,客户端是一个主动的合作伙伴,因为它主动发起一个连接。换句话说,首先启动服务器(在任何客户端试图连接之前)。

  在开发中,创建这种 “友好的” 退出方式的一种方法就是,将服务器的 while 循环放在一个 try-except 语句中的 except 子句中,并监控 EOFError 或 KeyboardInterrupt 异常,这样你就可以在 except 或 finally 子句中关闭服务器的套接字。

标签:02,socket,编程,TCP,服务器,接字,连接,客户端
From: https://www.cnblogs.com/kurome/p/17787987.html

相关文章

  • Python 面向对象编程:类、对象、初始化和方法详解
    Python是一种面向对象的编程语言。在Python中,几乎所有东西都是对象,都具有其属性和方法。类似于对象构造函数或用于创建对象的“蓝图”的类。创建一个类要创建一个类,请使用关键字class:示例,创建一个名为MyClass的类,其中包含一个名为x的属性:classMyClass:x=5创建......
  • 2023 CSP-S 二轮游记
    2023CSP-S二轮游记T1刚开始以为是个CQOI2018九连环那样的题目,导致心理认为题目很难,刚开始没看题面和样例,赛时直接去看T2了,后来发现T1给的样例2很适合分析,分析一顿发现T1很简单,考后发现大家貌似把状态压到了十进制或者是二进制里,只有我一个压到了字符串里()。T2以为......
  • 考场(NOIP2023模拟2联测23)
    T1一眼顶针鉴定不出来,二眼顶针看出来是贪心,对于一个序列来说肯定要选值小的数来拉低平均数,鉴定完毕T2有点东西,也许是要用\(kruskal\)或\(prim\)的思想做题???边从前向后遍历,若一个边不是树边,因为要保证树边权最小,所以每次要更新树边的边权,然后再更新非树边边权,更新树边边权时......
  • Python 面向对象编程:类、对象、初始化和方法详解
    Python是一种面向对象的编程语言。在Python中,几乎所有东西都是对象,都具有其属性和方法。类似于对象构造函数或用于创建对象的“蓝图”的类。创建一个类要创建一个类,请使用关键字class:示例,创建一个名为MyClass的类,其中包含一个名为x的属性:classMyClass:x=5创......
  • P9669 [ICPC2022 Jinan R] DFS Order 2 题解
    P9669[ICPC2022JinanR]DFSOrder2题解简要题意给定一棵\(n\)个节点的树,根节点是\(1\)。从根节点开始深度优先搜索这一棵树,dfs序是在搜索过程中访问节点的顺序。对于每一个节点\(v\),你要给出有多少种不同的dfs序,使得\(v\)出现在第\(j\)个位置。答案对\(99824......
  • Linux/UNIX系统编程手册 Michael Kerrisk/孙剑 pdf电子版
    Linux/UNIX系统编程手册MichaelKerrisk/孙剑pdf电子版下载作者: MichaelKerrisk / 孙剑原作名: TheLinuxProgrammingInterface:ALinuxandUNIXSystemProgrammingHandbook出版年: 2014-1ISBN: 9787115328670连接提取码:hfkr内容确实组织得比APUE更适合系统学习......
  • 2023中国物流系统集成商百强榜研究报告(附下载)
    随着智能物流建设的不断深入,企业应用了越来越多的自动化、智能化物流设备与管理软件。但各物流功能之间的效益背反问题如何解决? 各品牌与类型物流设备的接口各异如何统一调度? 各物流设备与管理软件之间的数据如联通传输?乃至物流设备与生产设备、物流管理软件与其他管理软件的......
  • 2023各版本JDK下载链接
    JavaArchive|OracleJavaArchive|Oraclehttps://www.oracle.com/java/technologies/downloads/archive/ ......
  • Python编程快速上手(第2版)2021年pdf电子版 Al Sweigart
    Python编程快速上手(第2版)2021年pdf电子版AlSweigart作者: [美]AlSweigart原作名: AutomatetheBoringStuffwithPython:PracticalProgrammingforTotalBeginners出版年: 2021-3-1ISBN: 9787115551870连接提取码:a0si本书用示例程序,介绍了一些实际的编程案例。建议自......
  • Metasploit Linux Reverse_Tcp Shellcode 源码分析
    分析Metasploitlinux/x64/shell/reverse_tcpshellcodeShellcode生成使用msfvenom生成c格式的stagedshellcode$msfvenom-plinux/x64/shell/reverse_tcp-fc-ax64--platformlinuxLHOST=192.168.48.233LPORT=4444Payloadsize:130bytesFinalsizeofcf......