>  기사  >  백엔드 개발  >  Python의 소켓 네트워크 프로그래밍

Python의 소켓 네트워크 프로그래밍

高洛峰
高洛峰원래의
2017-02-24 15:17:241568검색

인터넷이란 무엇인가요?

네트워크는 노드와 연결로 구성되며, 이는 많은 개체와 그 상호 연결을 나타냅니다. 수학에서 네트워크는 일종의 그래프로, 일반적으로 가중치 그래프를 특별히 지칭하는 것으로 간주됩니다. 수학적 정의 외에도 네트워크에는 특정한 물리적 의미도 있습니다. 즉, 네트워크는 특정 유형의 실제 문제에서 추상화된 모델입니다. 컴퓨터 분야에서 네트워크는 정보 전송, 수신, 공유를 위한 가상 플랫폼입니다. 다양한 지점, 표면, 신체의 정보를 함께 연결하여 이러한 리소스의 공유를 실현합니다. 인터넷은 인류 발전 역사상 가장 중요한 발명품으로서 과학기술과 인류사회의 발전을 향상시켰다.

네트워크 통신의 세 가지 요소

IP 주소
독립적인 호스트를 나타내는데 사용됩니다
특수 IP 주소 127.0.0.1 또는 localhost(로컬 루프백 주소, 예약된 주소 등을 나타냄)를 로컬 테스트에 사용할 수 있습니다

포트 번호
상대방이 지정한 애플리케이션에 데이터를 전송하기 위해 이러한 애플리케이션을 식별하기 위해 해당 네트워크 애플리케이션을 숫자로 식별합니다. 편의상 이 번호를 포트라고 합니다

전송 프로토콜
TCP 프로토콜: 전송 제어 프로토콜
연결 지향: 전송 전에 연결이 설정되어야 합니다
연결 과정에서 많은 양의 데이터가 전송됩니다
안전하고 안정적인 연결인 3방향 핸드셰이크를 통해 연결됩니다
전송 속도가 느리고 효율성이 낮습니다
UDP 프로토콜: 사용자 전송 프로토콜
비연결의 경우: 전송 프로세스에서 전송을 위해 연결 설정이 필요하지 않습니다.
각 데이터의 크기 전송은 64K로 제한됩니다
전송 프로세스가 불안정합니다
빠른 전송 속도와 높은 효율성

SOCKET 네트워크 프로그래밍

간단한 구현 웹 애플릿

import socket
def handle_request(client):
 buf = client.recv(1024)
 client.send(bytes("HTTP/1.1 200 OK\r\n\r\n",'utf8'))
 client.send(bytes("Hello, World",'utf8'))

def main():
 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 sock.bind(('localhost', 8080))
 sock.listen(5)

 while True:
  connection, address = sock.accept()
  handle_request(connection)
  connection.close()


if __name__ == '__main__':
 main()

Python은 두 가지 수준의 액세스 네트워크 서비스를 제공합니다.

저수준 네트워크 서비스는 기본 지원을 지원합니다. 기본 운영 체제 소켓 인터페이스에 액세스하기 위해 모든 메소드를 사용할 수 있는 표준 BSD 소켓 API를 제공하는 소켓.
네트워크 서버 개발을 단순화하기 위해 서버 센터 클래스를 제공하는 고급 네트워크 서비스 모듈인 SocketServer입니다.

소켓이란 무엇입니까?

소켓은 "소켓"이라고도 합니다. 애플리케이션은 일반적으로 "소켓"을 통해 네트워크에 요청하거나 응답합니다. 호스트 간 또는 컴퓨터 프로세스 간 통신.

소켓() 함수:

socket.socket([family[, type[, proto]]])

매개변수

family: 소켓 계열은 AF_UNIX 또는 AF_INET일 수 있습니다.
type: 소켓 유형은 연결 지향인지 비연결인지에 따라 SOCK_STREAM 또는 SOCK_DGRAM으로 나눌 수 있습니다.

소통과정

Python의 소켓 네트워크 프로그래밍


#######server端##########

import socket

sk = socket.socket()
address = ('127.0.0.1', 8000)
sk.bind(address)
sk.listen(3)

while True:
 conn, addr = sk.accept()
 while True:
  try:
   data = conn.recv(1024)
   print(str(data, 'utf8'))
   if not data:
    break
   inp = input(">>>")
   conn.send(bytes(inp, 'utf8'))
  except Exception:
   break

conn.close()

##########Client端###########
import socket

sk = socket.socket()
address = ('127.0.0.1', 8000)
sk.connect(address)
while True:
 inp = input(">>>")
 if inp == "exit":
  break
 sk.send(bytes(inp, 'utf8'))
 data = sk.recv(1024)
 print(str(data, 'utf8'))
sk.close()

소켓 내장 방식

s.bind()    绑定地址(host,port)到套接字, 在AF_INET下,以元组(host,port)的形式表示地址。
s.listen()  开始TCP监听。backlog指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了。
s.accept()  被动接受TCP客户端连接,(阻塞式)等待连接的到来

客户端套接字
s.connect() 主动初始化TCP服务器连接,。一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。
s.connect_ex()  connect()函数的扩展版本,出错时返回出错码,而不是抛出异常

公共用途的套接字函数
s.recv()    接收TCP数据,数据以字符串形式返回,bufsize指定要接收的最大数据量。flag提供有关消息的其他信息,通常可以忽略。
s.send()    发送TCP数据,将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。
s.sendall() 完整发送TCP数据,完整发送TCP数据。将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。
s.recvform()    接收UDP数据,与recv()类似,但返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。
s.sendto()  发送UDP数据,将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。
s.close()   关闭套接字
s.getpeername() 返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。
s.getsockname() 返回套接字自己的地址。通常是一个元组(ipaddr,port)
s.setsockopt(level,optname,value)   设置给定套接字选项的值。
s.getsockopt(level,optname[.buflen])    返回套接字选项的值。
s.settimeout(timeout)   设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如connect())
s.gettimeout()  返回当前超时期的值,单位是秒,如果没有设置超时期,则返回None。
s.fileno()  返回套接字的文件描述符。
s.setblocking(flag) 如果flag为0,则将套接字设为非阻塞模式,否则将套接字设为阻塞模式(默认值)。非阻塞模式下,如果调用recv()没有发现任何数据,或send()调用无法立即发送数据,那么将引起socket.error异常。
s.makefile()    创建一个与该套接字相关连的文件

实例


#########Server端##########

import socket
import subprocess

sk = socket.socket()
address = ('127.0.0.1', 8000)
sk.bind(address)
sk.listen(3)


while True:
 conn, addr = sk.accept()
 while True:
  try:
   data = conn.recv(1024)
  except Exception:
   break
  if not data:
   break

  # print(str(data, 'utf8'))
  # data = str(data, 'utf8')#解码同decode
  obj = subprocess.Popen(data.decode('utf8'), shell=True, stdout=subprocess.PIPE)
  ssh_result = obj.stdout.read()
  result_len = bytes(str(len(ssh_result)),'utf8')
  conn.send(result_len)

  conn.send(ssh_result)

conn.close()


#########Client#########


import socket

sk = socket.socket()
address = ('127.0.0.1', 8000)
sk.connect(address)

while True:
 inp = input(">>>")
 if inp == "exit":
  break
 sk.send(bytes(inp, 'utf8'))
 result_len = int(str(sk.recv(1024), 'utf8'))
 print(result_len)
 data = bytes()
 while len(data) != result_len:
  recv = sk.recv(1024)
  data += recv
 print(str(data, 'gbk'))
sk.close()

文件上传

Server

import socket
import os

sk = socket.socket()
address = ('127.0.0.1', 8000)
sk.bind(address)
sk.listen(3)

BASE_DIR = os.path.dirname(os.path.abspath(__file__))

while True:
 conn, addr = sk.accept()
 while True:
  data = conn.recv(1024)
  cmd, file_name, file_size = str(data, 'utf8').split('|')
  path = os.path.join(BASE_DIR, 'model', file_name)
  file_size = int(file_size)

  f = open(path, 'ab')
  has_recv = 0
  while has_recv != file_size:
   data = conn.recv(1024)
   f.write(data)
   has_recv += len(data)
  f.close()

Client

import socket
import os

sk = socket.socket()
address = ('127.0.0.1', 8000)
sk.connect(address)

BASE_DIR = os.path.dirname(os.path.abspath(__file__))

while True:
 inp = input(">>>>").strip()
 path = os.path.join(BASE_DIR, inp)

 file_name = os.path.basename(path)
 file_size = os.stat(path).st_size
 file_info = 'post|%s|%s' % (file_name, file_size)
 sk.sendall(bytes(file_info, 'utf8'))

 f = open(path, 'rb')
 has_sent = 0
 while has_sent != file_size:
  data = f.read(1024)
  sk.sendall(data)
  has_sent += len(data)

 f.close()
 print("上传成功")

socketserver

socketserver模块简化了网络编程服务程序的任务,同时SocketServer模块也是Python标准库中很多服务器框架的基础。

学习它的最好办法是自己浏览一遍它的源码。

首先先看一下如何去运用

import socketserver

class MyServer(socketserver.BaseRequestHandler):
 def handle(self):
  print("服务端启动")
  while True:
   conn = self.request

   while True:
    data = conn.recv(1024)
    print(str(data, 'utf8'))
    inp = input(">>>>>")

    conn.sendall(bytes(inp, 'utf8'))
   conn.close()

if __name__ == '__main__':
 server = socketserver.ThreadingTCPServer(('127.0.0.1', 8080), MyServer)
 server.serve_forever()

server

import socket

sk = socket.socket()

address = ('127.0.0.1', 8080)

sk.connect(address)
print("客户端启动")

while True:
 inp = input(">>>>>")
 sk.sendall(bytes(inp, 'utf8'))
 if inp == "q":
  break
 data = sk.recv(1024)
 print(str(data, 'utf8'))
sk.close()

此代码简单的实现了server端能同时和多个client聊天的功能。

我们在看源码前,首先要明确的是它分了几个类及每个类的功能作用等。

There are five classes in an inheritance diagram, four of which represent
synchronous servers of four types:

Python의 소켓 네트워크 프로그래밍

 下面的就不一一详细说了,想要了解的更透彻,还是看一遍源码吧。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支PHP中文网。

更多Python의 소켓 네트워크 프로그래밍相关文章请关注PHP中文网!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.