zoukankan      html  css  js  c++  java
  • python-socket网络编程笔记(UDP+TCP)

    端口

    在linux系统中,有65536(2的16次方)个端口,分为:

    知名端口(Well Known Ports):0-1023,如80端口分配给HTTP服务,21端口分配给FTP服务。

    动态端口(Dynamic Ports):1024-65535,一般不固定分配某种服务,而是动态分配。

    IP地址

    每一个IP地址包括两部分:网络地址和主机地址

    A类地址范围:1.0.0.1-126.255.255.254

    B类地址范围:128.1.0.1-191.255.255.254

    C类地址范围:192.0.1.1-223.255.255.254(常用)

    D类地址用于多点广播

    E类地址保留,仅作实验和开发用

    IP地址127.0.0.1~127.255.255.255用于回路测试

    socket

    socket(简称套接字) 是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于 Socket 来完成通信的。

    套接字使用流程:

    1. 创建套接字
    2. 使用套接字收/发数据
    3. 关闭套接字
    import socket
    
    # 创建udp的套接字
    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # 创建tcp的套接字
    tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # ...这里是使用套接字的功能(省略)...
    # 不用的时候,关闭套接字
    udp_socket.close()
    tcp_socket.close()

    UDP(User Datagram Protocol)

    中文名是用户数据报协议,是OSI(Open System Interconnection,开放式系统互联) 参考模型中一种无连接的传输层协议。

    创建一个基于udp的网络程序流程很简单,具体步骤如下:

    1. 创建[socket()]客户端套接字
    2. 发送[sendto()]/接收[recvfrom()]数据
    3. 关闭[close()]套接字

    UDP发送(客户端):

    import socket
    
    # 1. 创建udp套接字
    udp_socket = socket(AF_INET, SOCK_DGRAM)
    
    # 2. 准备接收方的地址
    # '192.168.1.103'表示目的ip地址
    # 8080表示目的端口
    dest_addr = ('192.168.1.103', 8080)  # 注意 是元组,ip是字符串,端口是数字
    
    # 3. 从键盘获取数据
    send_data = input("请输入要发送的数据:")
    
    # 4. 发送数据到指定的电脑上的指定程序中
    udp_socket.sendto(send_data.encode('utf-8'), dest_addr)
    
    # 5. 关闭套接字
    udp_socket.close()

    UDP接收(服务端):

    import socket
    
    # 1. 创建udp套接字
    udp_socket = socket(AF_INET, SOCK_DGRAM)
    
    # 2. 绑定IP和端口
    udp_socket.bind('',7788)
    
    # 3. 等待接收对方发送的数据
    recv_data = udp_socket.recvfrom(1024)  # 1024表示本次接收的最大字节数
    
    # 4. 显示对方发送的数据
    # 接收到的数据recv_data是一个元组
    # 第1个元素是对方发送的数据,需要使用发送时的字符集进行decode解码
    # 第2个元素是对方的ip和端口
    print(recv_data[0].decode('utf-8'))
    print(recv_data[1])
    
    # 5. 关闭套接字
    udp_socket.close()

    使用socket连接阿里云服务器

    客户端在window10本地,服务端在阿里云服务器上,让他们能够通信这里需要注意三点(前提是本地机器能够ping通阿里云服务器的公网IP):

    1、服务端绑定的IP地址需要为阿里云服务器的私有IP地址,即ifconfig中的ip,或者绑定时ip地址给空字符串'',这样也会默认绑定私有IP

    2、客户端连接的IP地址需要为阿里云服务器的公网IP地址,不能为私有IP。

    3、在阿里云控制台的安全组中需要开启相应的协议和端口权限,不然无法连接进阿里云服务器,协议为此次连接的协议,端口为服务器绑定的端口,授权对象为客户端的IP或者0.0.0.0/0表示所有IP都可访问

    TCP(Transmission Control Protocol)

    中文名是传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。

    TCP特点

    1. 面向连接

    通信双方必须先建立连接才能进行数据的传输,双方都必须为该连接分配必要的系统内核资源,以管理连接的状态和连接上的传输。

    双方间的数据传输都可以通过这一个连接进行。

    完成数据交换后,双方必须断开此连接,以释放系统资源。

    这种连接是一对一的,因此TCP不适用于广播的应用程序,基于广播的应用程序请使用UDP协议。

    2. 可靠传输

    1)TCP采用发送应答机制

    TCP发送的每个报文段都必须得到接收方的应答才认为这个TCP报文段传输成功

    2)超时重传

    发送端发出一个报文段之后就启动定时器,如果在定时时间内没有收到应答就重新发送这个报文段。

    TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的包发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失将会被进行重传。

    3)错误校验

    TCP用一个校验和函数来检验数据是否有错误;在发送和接收时都要计算校验和。

    4) 流量控制和阻塞管理

    流量控制用来避免主机发送得过快而使接收方来不及完全收下。

    TCP与UDP的不同点

    • 面向连接(确认有创建三方交握,连接已创建才作传输。)
    • 有序数据传输
    • 重发丢失的数据包
    • 舍弃重复的数据包
    • 无差错的数据传输
    • 阻塞/流量控制

    TCP编程

    客户端:

    1. 创建[socket()]客户端套接字
    2. 连接[connect()]服务器
    3. 发送[send()]数据
    4. 接收[recv()]返回的数据
    5. 关闭[close()]套接字
    import socket
    
    
    def main():
        # 创建套接字
        tcp_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 设置服务器地址
        server_addr = ('xxx.xxx.xxx', 7890) # 阿里云服务器公网IP
        # 创建连接
        tcp_client.connect(server_addr)
        while True:
            # 获取发送的数据
            send_data = input('请输入发送的数据(exit退出):
    ')
            if send_data == 'exit':
                break
            tcp_client.send(send_data.encode('utf-8'))
            # 接收服务端返回的数据
            recv_data = tcp_client.recv(1024)
            print('返回数据为:
    ', recv_data.decode('utf-8'))
        tcp_client.close()
    
    
    if __name__ == '__main__':
        main()

    服务端:

    1. 创建[socket()]服务端套接字
    2. 绑定[bind()]IP和端口
    3. 监听[listen()]将套接字变为可以被动链接
    4. 等待[accept()]客户端的连接,返回新的服务套接字服务于该客户端
    5. 新的服务套接字接收[recv()]数据
    6. 给客户端返回[send()]数据
    7. 关闭[close()]新的服务套接字
    8. 关闭[close()]监听的服务套接字
    import socket
    
    
    def client_server(client_socket):
        while True:
            # 接收数据
            recv_data = client_socket.recv(1024)
            if not recv_data:
                # 关闭服务套接字
                client_socket.close()
                break
            print('接收的数据为:', recv_data.decode('utf-8'))
            # 返回数据
            client_socket.send('已接收'.encode('utf-8'))
    
    
    def main():
        # tcp创建套接字
        tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 绑定端口
        local_addr = ('', 7890)
        tcp_server.bind(local_addr)
        # 使用listen将其变为被动
        tcp_server.listen(128)
        while True:
            print('准备接收连接.....')
            # 等待客户端连接,若有新客户端连接,返回一个新的套接字专门服务这个客户端
            client_socket, client_addr = tcp_server.accept()
            print('接收到连接,IP:%s PORT:%s' % (client_addr[0], client_addr[1]))
            client_server(client_socket)
    
        # 关闭监听的套接字
        tcp_server.close()
    if __name__ == '__main__':
        main()
  • 相关阅读:
    史上最全最新java面试题合集二(附答案)
    史上最全最新Java面试题合集一(附答案)
    修改vsftpd的默认根目录/var/ftp/pub到其他目录
    重置密码解决MySQL for Linux错误:ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
    虚拟机下的Linux连接校园网上网问题
    CentOS7 安装Chrome
    CentOS7 卸载Firefox
    100个写作高级词
    【二叉搜索树】的详细实现(C++)
    【红黑树】的详细实现(C++)
  • 原文地址:https://www.cnblogs.com/gcxblogs/p/12908683.html
Copyright © 2011-2022 走看看