python——网络编程

socket

简单讲先是server端发布一个服务,提供端口和IP,监听起来,就OK了。通过socket.send(bytes)给客户端发送消息,通过socket.recv(bytes)接收客户端的数据,进行处理

#!/user/bin/env python
# -*- coding:utf-8 -*-
# 模拟ssh

import socket, subprocess

#获取socket对象
s = socket.socket()

#获取socket参数
ip_port = (socket.gethostname(), 1234)
ip_port = (socket.gethostname(), 1234)
#创建服务
s.bind(ip_port)
#开启监听
s.listen(5)
while True:
    #等待连接
    conn, addr = s.accept()
    print(conn.getsockname(),"连接服务")
    while True:

        #获取连接消息
        res = conn.recv(1024)
        send_data = res
        p = subprocess.Popen(str(res, encoding='utf-8'), shell = True, stdout = subprocess.PIPE)
        send_data = p.stdout.read()
        print(type(send_data))
        if len(res) == 0:
            print(conn.getsockname(),'断开服务')
            break
        if send_data:
            send_data = str(send_data,encoding='gbk')
        else:
            send_data = 'command error!'
        print(send_data)
        #发送消息
        len_data = len(bytes(send_data,encoding='utf-8'))
        conn.send(bytes("%d"%len_data, encoding='utf-8'))
        to_recv = str(conn.recv(1024),encoding = 'utf-8')
        print(to_recv)
        if to_recv == 'Y' or to_recv == 'y':
            conn.send(bytes(send_data,encoding='utf-8'))
        else:
            print('不接收')
            conn.send(bytes("OK!不接收!",encoding='utf-8'))
    #关闭连接
    conn.close()

然后客户端根据提供的端口和IP去连接,通过socket.spend(bytes)发送数据给服务端,通过socket.recv(bytes)接收服务端数据

#!/user/bin/env python
# -*- coding:utf-8 -*-
# Author:hft

import socket

c = socket.socket()
ip_port = ("192.168.50.128", 1234)
c.connect(ip_port)

#发送消息
while True:
    sent_data = input(">>:")
    if sent_data == 'q' or sent_data == 'Q':
        break
    c.send(bytes(sent_data, encoding='utf-8'))
    res = int(str(c.recv(1024), encoding='utf-8'))
    print("字节长度为:",res,"是否收(Y/N)")
    to_recv = input(">>")
    c.send(bytes(to_recv, encoding='utf-8'))
    # recv_size = 0
    # recv_msg = b''
    # while recv_size < res:
    #     recv_data = c.recv(1024)
    #     recv_msg += recv_data
    #     recv_size += len(recv_data)
    # print(recv_size,res)
    recv_msg = c.recv(res)
    print(str(recv_msg, encoding='utf-8'))
c.close()

socket listen   提供可以有多少个连接

socket 粘包  如果接收数据长度超过recv的数值,则会被下一个recv函数去接收上个未接受完的数据,所以如果数据过长,需对数据长度进行判断,如果没有接收完,需写个循环持续接收,万不能一次接收很大的数据,这样会对网络有压力

socket 阻断   recv 和 append都有阻断效果,即没有数据或者链接过来,程序处于假死状态,一旦触发才会进行下面的代码

socketserver

socket在单对单链接时是没有问题的,但是网络的概念就是一对多或多对多的概念,而socket如果当下的链接未断开,则其他链接都会处于挂起状态,直到当前链接断开。socketserver提供了一个多线程的链接方式,通过它可以实现多并发的需求

多并发   多并发即是可以多个客户端链接一个服务端,而彼此不会有影响。

例子 ssh

#!/user/bin/env python
# -*- coding:utf-8 -*-
# ssh

import socketserver, subprocess

class MyServer(socketserver.BaseRequestHandler):

    def handle(self):
        conn = self.request
        print(conn.getsockname(), "连接服务")
        while True:

            # 获取连接消息
            try:
                res = conn.recv(1024)
                send_data = res
                p = subprocess.Popen(str(res, encoding='utf-8'), shell=True, stdout=subprocess.PIPE)
                send_data = p.stdout.read()
                print(type(send_data))
                if len(res) == 0:
                    print(conn.getsockname(), '断开服务')
                    break
                if send_data:
                    send_data = str(send_data, encoding='gbk')
                else:
                    send_data = 'command error!'
                print(send_data)
                # 发送消息
                len_data = len(bytes(send_data, encoding='utf-8'))
                conn.sendall(bytes("%d" % len_data, encoding='utf-8'))
                to_recv = str(conn.recv(1024), encoding='utf-8')
                print(to_recv)
                if to_recv == 'Y' or to_recv == 'y':
                    conn.sendall(bytes(send_data, encoding='utf-8'))
                else:
                    print('不接收')
                    conn.sendall(bytes("OK!不接收!", encoding='utf-8'))
            except Exception:
                print("异常!")
                break

if __name__ == '__main__':
    server = socketserver.ThreadingTCPServer(('192.168.11.86',1234), MyServer)
    server.serve_forever()

 多线程

python中通过threading来实现多线程,通过调用threading.Thread来调用不同的线程

threading.Thread(target=f1,args=(123,)):

    target:是调用的函数

    args:是函数的参数,是元组类型

setDaemon:默认值为False:表示主线程等待子线程结束 才会结束

          True:表示主线程不等待子线程结束,如果主线程先结束,则程序会直接结束

start:表示线程开始执行,前面无论定义了多少东西,都到这步才会开始执行线程。

import time ,threading, datetime


# def f1(i):
#     time.sleep(1)
#     print(i)
#     print(datetime.datetime.now())
#
# print(datetime.datetime.now())
# for j in range(10):
#     t1 = threading.Thread(target=f1, args=(j,))
#     t1.start()
def f1(arg):
    time.sleep(0.5)
    print(datetime.datetime.now())
    print(arg)

print(datetime.datetime.now())
t = threading.Thread(target=f1, args=(123,))
# f1(111)
t.setDaemon(True)#True,表示主线程不等待此子线程执行完毕。
t.start()#开始执行
t.join(0.9)#表示主线程到此,等待,直到子线程执行完毕,
        #参数,表示主线程在此处至多等待N秒,然后执行下面代码
print('end')

作用域

旧事重提,作用域,python作用域有几种情况

首先块级作用域,python中没有块级作用域,即一个方法、一个代码块中,无论在哪里定义了变量,在它的下面的代码块中都可调用、修改等:

a = 0
while a<1:
    a += 1
    b = 1
print(a,b)

执行结果:1 1

然后方法之间的变量是不可以直接调用,需要传参才可以进行变量的调用,需要返回值,才能进行变量修改:

def f1():
    a = 1
def f2():
    b = a
f2()

报错:
NameError: name 'a' is not defined

全局变量,这类变量可以在模块任何一处使用,不可直接去赋值,需要添加golable

a = 1
c = 1
b = []
def f1():
    a = 2
    b.append(2)
    global c
    c = 2
    print(a,b,c)
def f2():
    print(a,b,c)

f1()
f2()

执行结果:
  2 [2] 2   1 [2] 2

 

原文地址:https://www.cnblogs.com/fukuda/p/5640210.html