文档章节

Python 网络编程操作TCP/UDP 初探(二)

丰_申
 丰_申
发布于 2016/10/05 12:28
字数 1932
阅读 64
收藏 0

在上一章中我们遗留了下面几个问题:

1.异步通信,也是在不断的轮询排队处理中,如果采用服务器端多线程处理呢?

2.多线程与异步操作的异同

3.如果A - 服务器 -B该如何实现?(包含以下内容:

    a.半双工通信

    b.全双工通信

    c.多用户全双工通信

    d.使用多线程实现多用户全双工通信

    e.多用户、多房间、全双工通信

    )

针对上面的几个问题:我觉得是很有必要好好探索一下的。那么首先从多线程与异步操作的异同:

一.多线程与异步操作的异同

1.进程:

        每个进程都拥有自己的地址空间、内存、数据栈以及其它用于跟踪执行的辅助数据。需要采用ipc的方式共享信息。

2.线程:

        轻量级进程,在同一个进程下执行的,共享相同的上下文。可以将它们认为是在一个主进程或者“主线程”中并行运行的一些迷你进程,需要操作系统投入CPU资源来运行和调度。线程包含:开始、执行顺序和结束三部分。有一个指令指针,用于纪录当前运行的上下文,当其他线程运行时,它可以被抢占(中断)和临时挂起(睡眠),这种做法叫做让步。最重要的是一个进程中的各个线程与主线程共享同一片数据空间,因此相比于独立的进程而言,线程间的信息共享和通信更加容易。这种共享风险就是,如果多个线程访问同一片数据,由于访问的顺序不同,结果可能不一致。这种情况通常称为竞态条件(race condition)。有些线程可能还有阻塞状态,所以必须处理来避免cpu的时间过多的分配到这些贪婪线程。

3.多线程:

        之前有看到过知乎上的一个比喻,觉得特别好,在这里引用下:

单进程单线程:一个人在一个桌子上吃饭

单进程多线程:一群人在一个桌子上吃饭

多进程单线程:多个人在各自的桌子上吃饭

多线程容易引发的问题就是,一群人在一个桌子上吃饭的时候,如果同时有多个人要夹同一个菜,就容易一个人刚伸筷子,菜已经被别人夹走。所以必须一人夹一筷子。这就是资源冲突。

在windows上,创建进程会消耗会很大,所以鼓励大家在windows平台下进行单进程多线程操作。

在linux 上,创建进程的消耗很小,所以鼓励大家在各自的桌子上吃饭,但是这样就存在不同桌子互相讲话很困难。所以需要大家学习处理进程间的通信。

当在多核cpu上,每个cpu运行一个进程,有各自的进程资源,所以在cpu核心上切换无需考虑上下文。但是如果每个核心运行一个线程,每个线程需要共享资源,所以必须将一个核心上的资源拷贝到另一个核心才能继续运行,所以会耗费大量的开销。因此在多核服务器端编程,要习惯多进程而非多线程。

4.异步操作

        所谓异步,打个比方,就是如果一大群人都想你听他说话,那么你就给他们每人一分钟的时间说,大家轮流说,没说完的待会儿轮到时再继续说。也就是一个时间片的方法。异步处理基于两个前提。第一个前提是支持并发,当然这是基本前提。这里的并发并不一定要是并行,也就是说允许逻辑上异步,实现上串行;第二个前提是 支持回调(callback),因为并发的、异步的处理不会阻塞当前正在被执行的流程,所以“任务完成后”要执行的步骤应该写在回调中,绝大多数回调是通过函数来实现。

异步操作的优缺点:

  因为异步操作无须额外的线程负担,并且使用回调的方式进行处理,在设计良好的情况下,处理函数可以不必使用共享变量(即使无法完全不用,最起码可以减少共享变量的数量),减少了死锁的可能。当然异步操作也并非完美无暇。编写异步操作的复杂程度较高,程序主要使用回调方式进行处理,与普通人的思维方式有些初入,而且难以调试。

多线程的优缺点:
  多线程的优点很明显,线程中的处理程序依然是顺序执行,符合普通人的思维习惯,所以编程简单。但是多线程的缺点也同样明显,线程的使用(滥用)会给系统带来上下文切换的额外负担。并且线程间的共享变量可能造成死锁的出现。

针对他们是适用范围,如果针对大数据量的算法及图形处理,建议使用多线程进行操作。

二、实战,下面我们来实现下以下几个功能:

1.半双工通信

        半双工通信,就是只有一个人能打字,而另一个参与者在得到输入消息提示之前必须等待消息。并且,一旦发送者发送一了一条消息,在它能够再次发送消息之前,必须等待对方的回复。再上一章中,其实我们已经实现了,修改下部分代码,来更加完善:

服务器端:

# coding:utf-8
from socket import *
from time import ctime

HOST = ''
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST, PORT)

tcpSerSock = socket(AF_INET, SOCK_STREAM)  # 分配TCP服务器套接字
tcpSerSock.bind(ADDR)  # 将套接字绑定到服务器地址
tcpSerSock.listen(5)  # 开启TCP监听器,接受连接数6个,超过连接数拒绝连接!只与第一个连接客户端通信.

try:
    while True:
        print 'waiting for connection...'   # 无限循环中,等待客户端的连接
        tcpCliSock, addr = tcpSerSock.accept()
        print '...connected from:', addr
        try:
            while True:
                data = tcpCliSock.recv(BUFSIZE)  # 接收客户端数据
                if not data:  # 如果接收的消息是空白数据,这以为着客户端已经退出,跳出循环,关闭当前的客户端连接,继续等待另一个客户端连接
                    break
                else:
                    print ' Client To Ser [%s] %s' % (ctime(), data)
                    while True:
                        serRecData = raw_input('> ')
                        if not serRecData:
                            continue
                        else:
                            tcpCliSock.send(serRecData)  # 接受到客户端消息不为空,服务端输入信息返回给客户端。
                            print 'waiting for Client...'
                            break
        finally:
            tcpCliSock.close()
finally:
    tcpSerSock.close()  # 永远不会执行,只是提醒大家,可以用这种方式,关闭服务器套接字,退出服务

客户端:

# coding:utf-8
from socket import *
from time import ctime

HOST = 'localhost'
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST, PORT)

tcpCliSock = socket(AF_INET, SOCK_STREAM)  # 分配TCP套接字
tcpCliSock.connect(ADDR)  # 通过主机信息连接服务器
try:
    while True:
        data = raw_input('> ')   # 输入信息
        if not data:  # 如果输入为空,则跳出循环体,关闭客户端连接
            break
        tcpCliSock.send(data)  # 输入不为空,发送信息。
        print 'waiting for Ser...'
        data = tcpCliSock.recv(BUFSIZE)
        if not data:
            break
        print ' Ser To Client [%s] %s' % (ctime(), data)
finally:
    tcpCliSock.close()

 

服务器端显示:

客户端显示:

2.全双工通信

3.多用户全双工通信

4.使用多线程实现多用户全双工通信

5.多用户、多房间、全双工通信

 

© 著作权归作者所有

共有 人打赏支持
丰_申
粉丝 10
博文 179
码字总数 114855
作品 0
深圳
QA/测试工程师
python的Socket编程基础

下面一些是python网络编程基础知识,很少在项目中直接使用,都是用的twisted,gevent,tornado等网络框架.但是学习基础知识可以弄懂socket流程. python的socket模块的网络编程步骤和linux c基本一...

flyking
2013/10/23
0
0
python 网络编程之socket

在python socket编程主要是面各tcp 和 udp编程。下面我们就用这两种不同的编程方式来实现一个从客服端发送信息到服务器端, 服务器端返回客服器现在时间和接收到的信息 我们先来实现tcp的编程...

thinkyoung
2014/05/08
0
0
Python网络编程—第26课—Socket原理简介(0531)

一、Python网络编程——客户端/服务器架构 1、服务器:服务器就是一系列硬件和软件,为一个或多个客户端提供所需要的服务。存在的目的就是等待客户端的请求,并响应他它们,然后等待更多请求...

python初雪之路
05/29
0
0
Python实现基于TCP UDP协议的IPv4 IPv6模式客户端和服务端功能示例

本文实例讲述了Python实现基于TCP UDP协议的IPv4 IPv6模式客户端和服务端功能。分享给大家供大家参考,具体如下: 由于目前工作的需要,需要在IPv4和IPv6两种网络模式下TCP和UDP的连接,要做...

萌萌小白
04/27
0
0
Python Socket 编程概览

简评:socket 和 socket API 用于通过网络发送消息,它们提供了一种进程间通信(IPC)方式。网络可以是计算机的逻辑本地网络,也可以是物理连接到外部网络的网络,显而易见的例子是因特网(即...

极小光
09/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

linux使用ntfs-3g操作ntfs格式硬盘

Linux内核目前只支持对微软NTFS文件系统的读取。 NTFS-3G 是微软 NTFS 文件系统的一个开源实现,同时支持读和写。NTFS-3G 开发者使用 FUSE 文件系统来辅助开发,同时对可移植性有益。 安装 ...

linuxprobe16
今天
1
0
kubeadm部署kubernetes集群

一、环境要求 这里使用RHEL7.5 master、etcd:192.168.10.101,主机名:master node1:192.168.10.103,主机名:node1 node2:192.168.10.104,主机名:node2 所有机子能基于主机名通信,编辑...

人在艹木中
今天
7
0
Shell特殊符号总结以及cut,sort,wc,uniq,tee,tr,split命令

特殊符号总结一 * 任意个任意字符 ? 任意一个字符 # 注释字符 \ 脱义字符 | 管道符 # #号后的备注被忽略[root@centos01 ~]# ls a.txt # 备注 a.txt[root@centos01 ~]# a=1[root@centos01...

野雪球
今天
3
0
OSChina 周二乱弹 —— 程序员圣衣

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @达尔文:分享Skeeter Davis的单曲《The End of the World》 《The End of the World》- Skeeter Davis 手机党少年们想听歌,请使劲儿戳(这里...

小小编辑
今天
18
0
[ python import module ] 导入模块

import moudle_name ----> import module_name.py ---> import module_name.py文件路径 -----> sys.path (这里进行查找文件) # from app.web import Personimport app.web.Person as Pe......

_______-
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部