zoukankan      html  css  js  c++  java
  • 基于python的socket网络编程

    基于python的socket网络编程

    1. socket简介

    首先我们需要理解什么是网络编程,网络编程就是编写程序使两台联网的计算机之间能够进行通信,即能相互交换数据。

    然后我们再来理解socket,socket即套接字,是操作系统提供的独立于具体协议的网络编程接口,使用socket可以很方便地编写出数据传输程序,实现计算机之间的通信,而无需考虑其背后的原理。

    socket 的一个典型应用就是 Web 服务器和浏览器:浏览器获取用户输入的 URL,向服务器发起请求,服务器分析接收到的 URL,将对应的网页内容返回给浏览器,浏览器再经过解析和渲染,就将文字、图片、视频等元素呈现给用户。

    socket起源于Unix,而Unix类的操作系统有一个很好的设计理念,即一切皆文件,对文件使用【打开+读写+关闭】的模式进行操作。而socket即是一种特殊的文件,当我们通过socket()函数创建一个网络连接(或者说打开一个网络文件)时,socket()函数的返回值就是文件描述符,有了这个文件描述符,我们就可以使用普通的文件操作来传输数据了。

    2. 基于python的TCP Socket

    编程思路:

    1. TCP服务端
      • 创建套接字,并绑定到本地IP与端口
      • 开始监听客户端的连接
      • 进入循环,不断接受客户端的连接请求
      • 然后接收客户端传来的数据,并发送给客户端数据
      • 传输完毕后关闭套接字
    2. TCP客户端
      • 创建套接字,根据服务器的IP地址和端口号连接上服务器
      • 成功连接后发送数据并接收服务器传来的数据
      • 传输完毕后主动关闭套接字

    编程实现:

    客户端:

    import socket
    
    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    
    #设置服务器的ip地址和端口号
    #本地回环地址,范例为:同一台机器上两个进程间的通信
    host = '127.0.0.1'
    port = 9999
    
    s.connect((host,port))
    
    while True:
    	sendmsg = input("请输入要发送的数据:")
    	s.send(sendmsg.encode("utf-8"))	
    	msg = s.recv(1024)
    	if sendmsg == "exit":
    		break
    	print("收到来自服务器的消息:",msg.decode("utf-8"))
    s.close()
    

    服务端:

    import socket
    
    host = '127.0.0.1'
    port = 9999
    
    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    s.bind((host,port))
    s.listen(5)
    #开始等待客户端的连接
    client_s,addr = s.accept()
    print("连接上的客户端的ip地址和端口号:",addr)
    
    while True:
    	recvmsg = client_s.recv(1024)
    	data = recvmsg.decode("utf-8")
    	print("收到来自客户端的消息:",data)
    	if data == "exit":
    		break
    	msg = input("请输入要发送的数据:")
    	client_s.send(msg.encode("utf-8"))
    s.close()
    

    效果:

    先启动server,再启动client

    使用netstate -an命令查看已建立的连接:

    3. Python语言提供的网络接口API与Linux Socket API之间的关系 (很规整)

    Python API Linux Socket API
    s = socket.socket() socket()
    s.bind() bind()
    s.listen() listen()
    s.accept() accept()
    s.connect() connect()
    s.recv() recv()
    s.send() send()
    s.close() close()

    4. 为了证明API调用之间的对应关系,简要跟踪分析调用栈直到socket API接口

    无论何种语言提供的Socket API,底层都会调用BSD Socket,python也不例外。

    下面以python语言提供的s.close()API为例跟踪分析其调用栈:

    1. https://github.com/python/cpython/blob/master/Lib/socket.py socket.py的开头有这样一段描述:
    # Wrapper module for _socket, providing some additional facilities
    # implemented in Python.
    

    说明socket.py是用python语言把用c代码写的模块再一次封装,方便调用。

    在该文件的第497行对close()函数进行了定义:

    1. https://github.com/python/cpython/blob/master/Modules/socketmodule.c socketmodule.c的开头有这样一段描述:
    /* Socket module */
    
    /*
    This module provides an interface to Berkeley socket IPC.
    

    在该文件的第3120行可以找到s.close()方法的c实现,再下一层即调用SOCKETCLOSE():

    s.close()
    	->_real_close()
    		->sock_close()
    			->res = SOCKETCLOSE(fd)
    

    5. chrome浏览器打开一个网址

    套接字作为BSD Unix操作系统的一部分诞生于伯克利,随即像野火一样在Internet上传播,因为套接字与 INET 的结合使得世界各地的任意机器间通信变得令人难以置信的简单 。

    比如当我们打开科大官网的链接时,你的chrome浏览器就已经做了下面这几件事情:

    #本地创建一个套接字
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    #连接到科大服务器的80端口
    s.connect(("www.ustc.edu.cn", 80))
    #函数原型:socket.connect( (host,port) )
    #host代表服务器主机名或IP,port代表服务器进程所绑定的端口号。如连接成功,客户就可通过套接字与服务器通信,如果连接失败,会引发socket.error异常。
    

    连接完成后套接字就可以向服务端发送页面请求,

    那在服务端发生了什么呢:

    #首先服务端创建一个套接字
    serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    #将socket绑定到指定地址
    serversocket.bind((socket.gethostname(), 80))
    #函数原型:socket.bind( address )
    #由AF_INET所创建的套接字,address地址必须是一个双元素元组,格式是(host,port)。host代表主机,port代表端口号。如果端口号正在使用、主机名不正确或端口已被保留,bind方法将引发socket.error异常。
    serversocket.listen(5)
    #最多允许5个客户连接到服务器,队满则拒绝请求
    

    现在我们已经有一个服务端套接字,它监听服务器的80端口,接下来进入服务器的主循环:

    while True:
        (clientsocket, address) = serversocket.accept()
        ct = client_thread(clientsocket)
        ct.run()
        #服务端使用线程处理并发,并向客户端发送数据
        #每次会话结束,套接字描述符都会被回收
    

    参考资料:
    https://keelii.com/2018/09/24/socket-programming-in-python/

    https://www.cnblogs.com/csms/p/10117113.html

    https://docs.python.org/zh-cn/3/howto/sockets.html

    https://docs.python.org/zh-cn/3/library/socket.html

  • 相关阅读:
    从sql查询结果集中查询
    tsql中with用法
    tsql 2005 ROW_NUMBER
    基于对象的C#
    逍遥游
    Creating Custom Solutions for Document Collaboration
    Word template
    Jquery :nthchild 选择用法
    .net 转换任意类型不报错
    Dom 中同级元素 选择第几个的另类方法
  • 原文地址:https://www.cnblogs.com/huangmengyu/p/12025308.html
Copyright © 2011-2022 走看看