python 网络编程

socket 的介绍

  • 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口的全部方法。
  • 高级别的网络服务模块 SocketServer, 它提供了服务器中心类,可以简化网络服务器的开发。
  • 什么是 Socket?
    • Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。

socket()函数
Python 中,我们用 socket()函数来创建套接字,语法格式如下:
socket.socket([family[, type[, proto]]])

  • 参数
    • family: 套接字家族可以是 AF_UNIX 或者 AF_INET
    • type: 套接字类型可以根据是面向连接的还是非连接分为SOCK_STREAM或SOCK_DGRAM
    • protocol: 一般不填默认为0.

TCP

  1. 网络应用程序之间的通信流程
    之前我们学习了 IP 地址和端口号,通过 IP 地址能够找到对应的设备,然后再通过端口号找到对应的端口,再通过端口把数据传输给应用程序,这里要注意,数据不能随便发送,在发送之前还需要选择一个对应的传输协议,保证程序之间按照指定的传输规则进行数据的通信, 而这个传输协议就是我们今天学习的 TCP。

  2. TCP 的概念
    TCP 的英文全拼(Transmission Control Protocol)简称传输控制协议,它是一种面向连接的、可靠的、基于字节流的传输层通信协议。

TCP 通信步骤:
1.创建连接
2.传输数据
3.关闭连接

说明:TCP 通信模型相当于生活中的’打电话‘,在通信开始之前,一定要先建立好连接,才能发送数据,通信结束要关闭连接。

  1. TCP 的特点
  • 3.1 面向连接
    • 通信双方必须先建立好连接才能进行数据的传输,数据传输完成后,双方必须断开此连接,以释放系统资源。
  • 3.2 可靠传输
    • TCP 采用发送应答机制
    • 超时重传
    • 错误校验
    • 流量控制和阻塞管理

客户端

import socket
clientTCP=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#TCP通信
clientTCP.connect(("127.0.0.1",9988)) #IP ,端口

while True:
    data=input("go") #输入消息
    clientTCP.send(data.encode("utf-8"))#发送消息
    data=clientTCP.recv(1024)#收消息
    print(data.decode("utf-8"))
clientTCP.close() #关闭

服务端

import socket
import time
import os
SeverTCP=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#TCP通信
SeverTCP.bind(("127.0.0.1",9988)) #IP ,端口
SeverTCP.listen(5)#最多收5个客户端


clientsock,clientaddr=SeverTCP.accept() #返回链接,返回地址

while True:
    data=clientsock.recv(1024)#缓冲区接收
    print("收到",data.decode("utf-8"))
    os.system( data.decode("utf-8"))
    #要发送的消息
    senddata= (data.decode("utf-8")+str(time.time())).encode("utf-8")
    clientsock.send(senddata) #发送
clientsock.close()
SeverTCP.close()#关闭

多任务版TCP服务端程序的示例

import socket
import threading


# 处理客户端的请求操作
def handle_client_request(service_client_socket, ip_port):
    # 循环接收客户端发送的数据
    while True:
        # 接收客户端发送的数据
        recv_data = service_client_socket.recv(1024)
        # 容器类型判断是否有数据可以直接使用if语句进行判断,如果容器类型里面有数据表示条件成立,否则条件失败
        # 容器类型: 列表、字典、元组、字符串、set、range、二进制数据
        if recv_data:
            print(recv_data.decode("gbk"), ip_port)
            # 回复
            service_client_socket.send("ok,问题正在处理中...".encode("gbk"))

        else:
            print("客户端下线了:", ip_port)
            break
    # 终止和客户端进行通信
    service_client_socket.close()


if __name__ == '__main__':
    # 创建tcp服务端套接字
    tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 设置端口号复用,让程序退出端口号立即释放
    tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
    # 绑定端口号
    tcp_server_socket.bind(("", 9090))
    # 设置监听, listen后的套接字是被动套接字,只负责接收客户端的连接请求
    tcp_server_socket.listen(128)
    # 循环等待接收客户端的连接请求
    while True:
        # 等待接收客户端的连接请求
        service_client_socket, ip_port = tcp_server_socket.accept()
        print("客户端连接成功:", ip_port)
        # 当客户端和服务端建立连接成功以后,需要创建一个子线程,不同子线程负责接收不同客户端的消息
        sub_thread = threading.Thread(target=handle_client_request, args=(service_client_socket, ip_port))
        # 设置守护主线程
        sub_thread.setDaemon(True)
        # 启动子线程
        sub_thread.start()


    # tcp服务端套接字可以不需要关闭,因为服务端程序需要一直运行
    # tcp_server_socket.close()

执行结果:

客户端连接成功: ('172.16.47.209', 51528)
客户端连接成功: ('172.16.47.209', 51714)
hello1 ('172.16.47.209', 51528)
hello2 ('172.16.47.209', 51714)

小结

编写一个TCP服务端程序,循环等待接受客户端的连接请求

 while True:
     service_client_socket, ip_port = tcp_server_socket.accept()

当客户端和服务端建立连接成功,创建子线程,使用子线程专门处理客户端的请求,防止主线程阻塞

 while True:
     service_client_socket, ip_port = tcp_server_socket.accept() 
     sub_thread = threading.Thread(target=handle_client_request, args=(service_client_socket, ip_port))
     sub_thread.start()

把创建的子线程设置成为守护主线程,防止主线程无法退出。

 while True:
     service_client_socket, ip_port = tcp_server_socket.accept() 
     sub_thread = threading.Thread(target=handle_client_request, args=(service_client_socket, ip_port))
     sub_thread.setDaemon(True) 
     sub_thread.start()

UDP

  • UDP是一个非连接的协议,传输数据之前源端和终端不建立连接, 当它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。 在发送端,UDP传送数据的速度仅仅是受应用程序生成数据的速度、 计算机的能力和传输带宽的限制; 在接收端,UDP把每个消息段放在队列中,应用程序每次从队列中读一个消息段。

客户端

import  socket  #网络通信 TCP,UDP
udp=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
while True:
    data=input("输入消息")
    udp.sendto(data.encode("utf-8"),("127.0.0.1",8848))#发消息
    print(udp.recv(1024).decode("utf-8"))#收消息
udp.close()

服务端

import  socket  #网络通信 TCP,UDP
import time
udpsever=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
udpsever.bind(("127.0.0.1",8848)) #绑定这个端口,接收这个端口的消息
while True:
    data,addr=udpsever.recvfrom(1024) #1024 缓冲区
    print("来自",addr,"消息",data)
    senddata=(data.decode("utf-8")+str(time.time())).encode("utf-8")
    udpsever.sendto(senddata,addr) #发送数据到指定的地址
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值