易语言与python互通_[我叫以赏]Python制作交互式的服务器与客户端互相通讯(引用SOCKET模块)...

前言

欢迎来到我的教程啊,我是以赏,这么说吧,Python我也在学习并未达到“精通”的地步,一部分呢是自学,一部分是老师“传授”的。但我认为学习Python应该“学以致用”(学其它也一样)。易语言的领域呆久了,出来混混Python(嘻嘻嘻)。感谢知乎平台,就因为这样我才有机会发布这篇文章。以及网上的自学资源少之又少,对新手不友好,而且大部分资源标着“转载”的标识,那么我学会了Python服务器与客户端的通讯,要把它写成文章分享出来,OK,第一次在知乎发布文章,请见谅......文末有资源下载哦!

所用到的材料与材料的讲解

Python:是一种计算机编程语言。是一种面向对象的动态类型语言,最初被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新功能的添加,越来越多被用于独立的、大型项目的开发。(摘自360百科)

Python中的socket模块:提供了服务器与客户端通讯的条件,它提供了标准的 BSD Sockets API,Python自带。(Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯)

Python中的threading模块:用于多线程的操作,“threading”是“穿线(线程)”的意思。

另外还需要一款你上手的Python IDE。

思路

网上大部分思路近似与这张图普通服务器

这种思路只可以,允许一个客户端连接,而且当一个客户端连接后,整个程序会以堵塞的状态继续运行(等待客户时,下面的代码不会运行,下面详细讲解)。

所以我们加上多线程,如下并行的服务器

这个思路图采取了多线程的方法(即支持并行),当线程①开启等待客户连接,连接后又开启一个新的线程,继续等待客户了连接,线程①在与客户交互时,并不妨碍线程②等待连接客户,此类方法有效的避免了堵塞的问题。(小提示:并行,类似于你再玩游戏,有人敲门,你一边玩游戏一边开门接待客人)

线程的简单说明

线程:是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。进程与线程之间是包含关系。下面是一个比较通俗的图:进程与线程的包含关系

当进程启动时(你的程序被运行时),主线程就开始了,我们来看一看下面的图线程与子线程的关系

主线程是当一个进程被创建,于此同时这个进程一个线程也被创建,通常我们叫这个线程叫主线程,主线程像学校中的校长一样,有权限处理学校大事与规定放学时间。主线程还可以开启若干个子线程,校长可以雇几个班主任来上课。当主线程结束时,程序也就结束了(在没有开子线程的条件下)。

子线程通常是辅助主线程的线程。当开启子线程时,主线程仍然可以继续运行(子线程与主线程并行)。

Python中线程的实现

请看下方代码逐句解析:

# -*- coding: utf-8 -*

import threading # 引入 threading 模块 在下文作用于多线程

import time # 映入 time 模块 在下文作用于延迟

a = 0 # 声明一个变量 在下文用作于技术

def calculate():

"""这个函数用户测试线程"""

global a # 声明全局变量a

while True: # 指定一个循环

a = a + 1 # a为记录循环的次数

if __name__ == "__main__": # 代码开始

cal = threading.Thread(target=calculate) # 启动线程的写法之一

cal.start() # 开启线程

time.sleep(5) # 延迟5秒

print(a) # 查看循环次数

结果(5秒后打印):线程结果

(结果因配置而异)

while循环会“暂停”程序,循环不结束,循环的下方代码不执行,相当于把循环所在的线程进入了一个暂停的状态。

cal = threading.Thread(target=calculate) # 启动线程的写法之一

cal.start() # 开启线程

重点是这两段代码,对于 Thread 类的注释官方是这样的:A class that represents a thread of control.

This class can be safely subclassed in a limited fashion. There are two ways

to specify the activity: by passing a callable object to the constructor, or

by overriding the run() method in a subclass.

表示控制线程的类。

可以通过有限的方式安全地将此类归为一类。有两种方法

指定活动:通过将可调用对象传递给构造函数,

或通过覆盖子类中的run()方法。

官方对于“threading.Thread()”的注释:This constructor should always be called with keyword arguments. Arguments are:

*group* should be None; reserved for future extension when a ThreadGroup

class is implemented.

*target* is the callable object to be invoked by the run()

method. Defaults to None, meaning nothing is called.

*name* is the thread name. By default, a unique name is constructed of

the form "Thread-N" where N is a small decimal number.

*args* is the argument tuple for the target invocation. Defaults to ().

*kwargs* is a dictionary of keyword arguments for the target

invocation. Defaults to {}.

If a subclass overrides the constructor, it must make sure to invoke

the base class constructor (Thread.__init__()) before doing anything

else to the thread.

始终应使用关键字参数来调用此构造函数。参数为:

*group* 应该为 None; 当线程组类已实现。

*target* 是run()可调用的对象,默认为“无”,表示不调用任何内容。

*name* 是线程名。默认情况下,唯一的名称由“Thread-N”的形式,其中N是一个小的十进制数。

*args* 是目标函数的参数——元组。默认为()。

*kwargs* 是目标函数的参数——字典。默认为{}。

如果子类重写构造函数,则必须确保调用基类构造函数(Thread)

上述中target是目标函数的名称,name为线程标记名,args为传入数据的元组,kwargs为传入的字典。

使用 threading.Thread(target=calculate) 呢,要使用start或run启动线程,这里就不多加赘述,线程最后再看一下传入参数吧。

# -*- coding: utf-8 -*

import threading # 引入 threading 模块 在下文作用于多线程

import time # 映入 time 模块 在下文作用于延迟

a = 0 # 声明一个变量 在下文用作于技术

def calculate(*args, **kwargs):

"""这个函数用户测试线程"""

print(args, kwargs) # 打印参数

if __name__ == "__main__": # 代码开始

cal = threading.Thread(target=calculate, args=("元组", "参数"), kwargs={"字典参数": "参数"}) # 启动线程的写法之一

cal.start() # 开启线程

time.sleep(5) # 延迟5秒

print(a) # 查看循环次数

打印出来的结果:线程传参

Python中服务器与客户端通讯的简单例子

这个标题里,我们展现简单的例子(不支持并行),这个标题内会讲的详细一点。

先看第一段代码:

# -*- coding: utf-8 -*

import socket # 引入 socket 模块

Server=socket.socket() # 创建一个socket对象

当然,你也或许会看到有些人的代码是这样写的:

socket.socket(socket.AF_INET, socket.SOCK_STREAM)

没错,socket.socket有4个参数,family(int), type(int), proto(int), fileno(bool)

官方在下方给的注释:For user code address family and type values are IntEnum members, but

for the underlying _socket.socket they're just integers. The

constructor of _socket.socket converts the given argument to an

integer automatically.

对于用户代码,地址族和类型值是IntEnum成员,但是对于底层的_socket.socket来说,它们只是整数。的_socket.socket的构造函数将给定参数转换为自动整数。

官方的话对参数的解释起不到大作用,但有两个参数我是可以解决的。

family:地址族,地址族如下socket.AF_UNIX :只能够用于单一的Unix系统进程间通信

socket.AF_INET :服务器之间的网络通信(ipv4协议的TCP和U

你可能感兴趣的:(易语言与python互通)