当前位置:   article > 正文

python网络编程 udp和tcp_client_socket.connect(('192.168.1.103',5678))

client_socket.connect(('192.168.1.103',5678))

UDP — 用户数据报协议(User Datagram Protocol)

  • 是一个无连接的简单的面向数据报的运输层协议。
  • UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。
  • 由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快。
udp服务器
import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(("192.168.1.103", 8888))
while True:
    data, addr = s.recvfrom(1024)
    print("%s : %s" % (str(addr), data.decode("gbk")))
    msg = input("客服请输入:")
    s.sendto(msg.encode("utf-8"), addr)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
udp客户端
import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True:
    msg = input("用户说话:")
    addr = ("192.168.1.103", 8080)
    s.sendto(msg.encode("utf-8"), addr)
    data = s.recvfrom(1024)
    print("%s : %s" % (str(data[1]), data[0].decode("gbk")))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • SOCK_STREAM(流式套接字,主要⽤于TCP协议)或者 SOCK_DGRAM(数据报套接字,主要⽤于UDP协议)

  • 绑定端口和TCP一样,但是不需要调用listen()方法,而是直接接收来自任何客户端的数据。

  • UDP是没有连接的,所以不需要三次握手,也就不需要调用listen和connect。

  • 因为没有连接状态,每次通信的时候,udp都调用sendto和recvfrom,可以传入IP地址和端口。

  • data表示接受到的传来的数据,是bytes类型,

  • data.encode(“utf-8”)编码,将字符串类型转换为bytes类型。

  • data.decode(“gbk”)解码,将bytes类型转换为字符串类型。 以发送方的编码格式为准

TCP — 传输控制协议

  • 传输控制协议是一种面向连接的、可靠的、基于字节流的传输层通信协议
  • 常用于web服务器开发,因为它具有稳定性,且速度仅较udp稍慢。
  • tcp通信需要经过创建连接、数据传送、终⽌连接三个步骤
tcp服务器
  • 服务器一般都需要绑定端口号,客户端不需要,让系统随机分配
import socket

def main():
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind(("192.168.1.103", 8888))
    server_socket.listen(11)  # 半连接池  在服务端会有一个队列,这里代表服务端最高只能接受11个请求数(并不是连接数)
    while True:
        print("等待新用户链接.....")
        client_socket, addr = server_socket.accept()
        print("%s   已成功连接" % str(addr))
        while True:
            data = client_socket.recv(1024)
            if not data:	# 如果为空 就是客户断开链接 结束对话
                print("%s   已断开链接 结束对话" % str(addr))
                break
            print("%s : %s" % (str(addr), data.decode("gbk")))
            msg = input("客服请输入:")
            client_socket.send(msg.encode("utf-8"))

if __name__ == "__main__":
    main()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
tcp客户端
import socket

def main():
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    ip = input("请输入目标IP:")
    port = int(input("请输入目标端口:"))
    addr = (ip, port)
    
	# 链接服务器,进行tcp三次握手
    client_socket.connect(addr)
    while True:
        msg = input("用户输入:")
        client_socket.send(msg.encode("utf-8"))
        # 接收对方发送过来的数据,最大接收1024个字节
        data = client_socket.recv(1024)
        print("%s : %s" % (str(addr), data.decode("gbk")))
    client_socket.close()

if __name__ == "__main__":
    main()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
tcp的优势
  • tcp面向连接(确认有创建三次握手,连接已创建才作操作),udp面向数据报
    通信双⽅必须先建⽴连接才能进⾏数据的传输,双⽅都必须为该连接分配必 要的系统内核资源,以管理连接的状态和连接上的传输。双⽅间的数据传输都可以通过这⼀个连接进⾏。完成数据交换后,双⽅必须断开此连接,以释放系统资源。这种连接是⼀对⼀的,因此TCP不适⽤于⼴播的应⽤程序,基于⼴播的应⽤ 程序请使⽤UDP协议。

  • 超时重传
    发送端发出⼀个报⽂段之后就启动定时器,如果在定时时间内没有收到应答 就重新发送这个报⽂段。
    TCP为了保证不发⽣丢包,就给每个包⼀个序号,同时序号也保证了传送到 接收端实体的包的按序接收。然后接收端实体对已成功收到的包发回⼀个相 应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确 认,那么对应的数据包就被假设为已丢失将会被进⾏重传。

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

  • 流量控制和阻塞管理
    流量控制⽤来避免主机发送得过快⽽使接收⽅来不及完全收下
    使⽤socket创建的套接字默认的属性是主动的,使⽤listen将其变为被动的,这样就可以接

tcp注意点
  • tcp服务器⼀般情况下都需要绑定,否则客户端找不到这个服务器
  • tcp客户端⼀般不绑定,因为是主动链接服务器,所以只要确定好服务器 的ip、port等信息就好,本地客户端可以随机
  • tcp服务器中通过listen可以将socket创建出来的主动套接字变为被动的, 这是做tcp服务器时必须要做的
  • 当客户端需要链接服务器时,就需要使⽤connect进⾏链接,udp是不需要链接的而是直接发送,但是tcp必须先链接,只有链接成功才能通信
  • 当⼀个tcp客户端连接服务器时,服务器端会有1个新的套接字,这个套接字用来标记这个客户端,单独为这个客户端服务
  • listen() 函数可以让套接字进入被动监听状态,接收请求需要使用 accept() 函数,accept返回的新套接字是标记这个新客户端的
  • 客户端的套接字调用close后,服务器端会recv解堵塞,并且返回长度为0,因此服务器可以通过返回数据的长度来区别客户端是否已经下线

案例 文件下载器

客户端

import socket

def main():
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    ip = input("请输入目标服务器IP:")
    port = int(input("请输入目标服务器端口:"))
    addr = (ip, port)
    client_socket.connect(addr)
    file_name = input("请输入文件名:")
    client_socket.send(file_name.encode("utf-8"))
    data = client_socket.recv(1024*1024)
    while data:
        with open("new" + file_name, "wb") as f:
            f.write(data)
    client_socket.close()

if __name__ == "__main__":
    main()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

服务器

import socket

def get_content(file_name):
    try:
        with open(file_name, "rb") as f:
            content = f.read()
            return content
    except:
        print("没有下载的文件%s" % file_name)

def main():
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind(("192.168.1.103", 8888))
    server_socket.listen(11)
    while True:
        client_socket, addr = server_socket.accept()
        print("%s 已成功连接准备下载文件....")
        data = client_socket.recv(1024)
        file_name = data.decode("utf-8")
        print("要下载的文件名是 %s" % file_name)
        file_content = get_content(file_name)
        # 因为是rb读取的 read(xxx, "rb")操作返回的是bytes 所以无需编码
        if file_content:
            client_socket.send(file_content)
        client_socket.close()

if __name__ == "__main__":
    main()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/195515
推荐阅读
相关标签
  

闽ICP备14008679号