Python网络编程(TCP协议基础、附代码)

#网络编程
#ip地址的作用:在互联网/局域网上唯一的标识一台电脑

#ip地址的分类
    A类:1字节(0 + 7*网络号)+ 3字节(主机号)
    B类:1字节(10 + 6*网络号)+ 1字节(网络号) + 2字节(主机号)
    C类:1字节(110 + 5*网络号)+ 2字节(网络号) + 1字节(主机号)
    D类:1110 + ...用于多播
    E类:11110 + ...保留

#单播:针对一个对象
#多播:针对一个群组
#广播:针对所有计算机

#xxx.xxx.xxx.0 和 xxx.xxx.xxx.255 不能用

#端口:区分一个ip网络下哪个进程!!!大小为0-65535,

#端口分类
    知名端口(0-1023):大家都默认使用的端口,比如80端口给HTTP服务,21端口给FTP服务
    动态端口(1024-65535):指当一个进程需要网络程序需要网络通信时,向主机申请一个端口,主机从可用端口中分配一个给进程
    

#传输层提供的通信类型:
    面向连接的可靠服务 ----> TCP协议(Transmission Control Protocol 传输控制协议)
    面向无连接的不可靠服务 ----> UDP协议(User Datagram Protoco 用户数据报协议)
    
    TCP协议规定:
        传输服务必须建立连接:三次握手
        传输结束必须断开连接:四次挥手
        传输数据必须保证可靠

#TCP连接时三次握手
    1、客户端发送一个ACK标志位
    2、服务端接收到请求后告诉客户端可以连接;或者拒绝连接
    3、客户端收到恢复之后,告知服务端,已收到,下面发送具体消息
    
#数据可靠性:
    数据无重复,无丢失,无失序,无错误

#TCP断开连接时四次挥手
    1、主动方发送标志位告知被动方要断开连接
    2、被动方返回相应标志位告知主动方已经接收到请求
    3、主动方再次发送标志位信息表示已经准备好断开,可以断开
    4、被动方断开连接并发送已经断开信息

#UDP协议
    不保证数据完整性
    数据的发送都是由发起端决定的,不考虑接收端的情况

#通信协议的选择
    TCP    
    1、对传输质量要求较高,需要可靠传输
    2、传输数据量大,不需要频繁的连接
    e.g.qq消息,邮件发送,文件上传,账户登陆
    
    UDP
    1、对实时性要求高,完整性要求不高
    2、网络状况不佳,完整性要求不高
    3、建立必要的非连接情况,如广播组播

#套接字socket分类
    流式套接字:传输层用TCP协议提供面向连接的创数服务
    数据包套接字:传输层用UDP协议提供面向无连接的传输服务
    原始套接字:一般用于底层协议测试(用不到)
    
#服务端创建TCP服务器的基本流程
1、创建流式套接字
    socket.socket(family = AF_INEF, type = SOCK_STREAM, proto = 0)
    参数:
        family:协议族类型 
            AF_UNIX:仅用于单一的Unix系统进程间相互通信
            AF_INET:服务器的网络通信
            AF_INET6:使用IPv6的服务器网络通信
        type:套接字类型
            SOCK_STREAM TCP流式套接字
            SOCK_DGRAM UDP数据报套接字
            SOCK_RAW 底层套接字
        proto:子协议选项(通常为0,因为一般情况下传输层没有子协议)
    返回:套接字对象
            
2、绑定本机IP和端口
    sock.bind()
    参数:For IP sockets, the address is a pair (host, port)即(主机名,端口号)
        比如("localhost", 8888)("",8888)("127.0.0.1(回环测试IP)",8888)只有本机进程能够连接服务器
        ("0.0.0.0",8888),("192.168.137.111(本地IP)",8888)(局域网其他成员都可以访问)

3、将套接字变为监听状态
    sockfd.listen(n)
    功能:将套接字设置为监听套接字,并设置一个连接等待队列,避免连接争夺,服务器按照顺序处理
    参数:正整数,表示等待队列的大小(Linux下是没用的,系统自动设定,win和mac下有用)

4、套接字等待连接,然后连接
    conn, addr = sockfd.accept()    
    功能:阻塞等待客户端的连接
    参数:无
    返回值:
        conn:和客户端进行交互的新套接字
        addr:连接进来的客户端的ADDR(IP & PORT)
    
5、收发消息
    conn.recv(buffer_size)
    功能:阻塞接收一个消息
    参数:一次从缓冲区得到的消息的最大大小(字节);如果没有那么大,得到所有消息,如果比那个大,则拿buffer_size个字节
    返回值:收到的消息,一般格式为bytes

    conn.send(data)
    功能:发送消息
    参数:要发送的内容;python3中要求send的必须是字节数组,即bytes格式
    返回值:实际发送的字节数
    
6、关闭套接字
    conn.close()    #表示当前连接的客户端连接断开
    sockfd.close()    #表示不再接收请求#示例代码:

from socket import *

IP = "127.0.0.1"
PORT = 8888
ADDR = (IP, PORT)
BUFFERSIZE = 128


sockfd = socket(AF_INET, SOCK_STREAM, 0)

sockfd.bind(ADDR)

sockfd.listen()

conn, addr = sockfd.accept()

recv_data = conn.recv(BUFFERSIZE)

conn.send(bytes("I am WilliamCode"))

conn.send("This is the second message!")

conn.close()
sockfd.close()


#客户端和服务端的套接字的类型必须一致

#创建客户端
1、创建客户端套接字
    connfd = socket(AF_INET, SOCK_STREAM)
2、绑定bind(可以没有,如果没有,IP为本地IP,PORT随机分配)
3、连接
    connfd.connect(address)
    功能:连接服务器
    参数:For IP sockets, the address is a pair (host, port),即(服务器IP,服务器端口号)
4、关闭
    connfd.close()

*注意点:
    1、客户端与服务端套接字类型必须相同
    2、客户端就是用创建的套接字和服务器交互
    3、recv和send要同步,防止死阻塞#示例代码:

import socket

SERVER_IP = "192.168.31.129"
SERVER_PORT = 8888
SERVER_ADDR = (SERVER_IP, SERVER_PORT)
BUFFER_SIZE = 1024

connfd = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

connfd.connect(SERVER_ADDR)


connfd.send("Hello Server!".encode())


recv_data = connfd.recv(BUFFER_SIZE)
print("Received from server", recv_data.decode())


connfd.close()

#send和sendall函数是一样的,只是发送失败时报错
#如果send的数据特别大,实际发送字节数可能比数据的小,会发送两次

#代码:服务器接收多个客户端的多个消息,客户端发送多个消息

#!server.py

客户端

from socket import *

IP = "192.168.31.129"
PORT = 8888
ADDR = (IP, PORT)
BUFFERSIZE = 128


sockfd = socket(AF_INET, SOCK_STREAM, 0)

sockfd.bind(ADDR)
sockfd.listen()

while True:

    conn, addr = sockfd.accept()
    
    while True:
        try:
            recv_data = conn.recv(BUFFERSIZE)    
        except:
            break    
        print("Connection from IP: %s, PORT: %d" % (addr[0], addr[1]))

        print("Received Data:", recv_data.decode())

        conn.send("Ragor that, client!".encode())

    conn.close()
sockfd.close()


#!client.py

客户端

import socket

SERVER_IP = "192.168.31.129"
SERVER_PORT = 8888
SERVER_ADDR = (SERVER_IP, SERVER_PORT)
BUFFER_SIZE = 1024

connfd = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

connfd.connect(SERVER_ADDR)

while True:
    msg = input("Please input the msg: ")
    if not msg:
        break
    connfd.send(msg.encode())


connfd.close()


#TCP循环服务不能满足多个客户端同时连接的情况,它不允许多个客户端同时占有客户端资源


 

发布了86 篇原创文章 · 获赞 56 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/WilliamCode/article/details/86438364