CodeSky 代码之空

随手记录自己的学习过程

Python 从多人聊天室开始谈系列 - Socket

2016-04-09 13:25分类: Python评论: 0

接下来我们首先略过了Python的基础,这一部分,随便找一本Python的书看看就行了,习惯了没有;的人生之后,在必须的语句里记得加:,基本上你就进入了Python模式。

当然,由于赶时间,这里很多可能不是最优写法,大家可以去GitHub提出=v=。

官网Demo有云:

1# Echo server program
2import socket
3
4HOST = ''                 # Symbolic name meaning all available interfaces
5PORT = 50007              # Arbitrary non-privileged port
6s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
7s.bind((HOST, PORT))
8s.listen(1)
9conn, addr = s.accept()
10print 'Connected by', addr
11while 1:
12    data = conn.recv(1024)
13    if not data: break
14    conn.sendall(data)
15conn.close()
16
1# Echo client program
2import socket
3
4HOST = 'daring.cwi.nl'    # The remote host
5PORT = 50007              # The same port as used by the server
6s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
7s.connect((HOST, PORT))
8s.sendall('Hello, world')
9data = s.recv(1024)
10s.close()
11print 'Received', repr(data)
12

看不懂,别急,我们慢慢来,首先看Server部分,我们首先初始化好服务器并且传入主机(Host)和端口(Port),s.listen()表示你的队列能有多长,s.accept()是一个阻塞式函数,关于什么是阻塞,之后我们就能感受到了,去监听客户端发来的连接。

recv()表示一次获取字符的最大长度,而sendall()则是发送数据,至于sendall()send()的区别,在于一次性发送与分批逐步发送,换句话说,如果你需要使用send()去发送,可能需要一个循环来达成。

接下来在Client中,我们使用connect()去连接,其他函数相同。

这里值得额外说明一个无关的函数repr(),如果你之前没有接触过Python,可能会比较陌生,总之,你可以把它看成一个转换为字符串的函数。

当然,我们要把它转换为我们上一篇文章中所示的模型,还是需要下一点功夫的。

首先,我们就会发现,Client和Server都已经自动断开了,这显然不符合我们的需求,我们用一个while循环来保持他们。

我们的Client需要接收输入,这里我们用Python2,简单的来使用raw_input来处理,后期使用GUI来包装我们的程序之后会改动。

1import socket
2
3s = socket.socket()
4
5host = socket.gethostname()
6port = 1234
7
8s.connect((host, port))
9print s.recv(1024)
10s.sendall('Hello World')
11while 1:
12    word = raw_input('>')
13    s.sendall(word)
14    print s.recv(1024)
15

Client改成了这样,就差不多成型了,当然使用之后我们才会发现很多问题。

接下来我们需要编写Server,Server编写起来稍微复杂一些,首先先考虑转发问题,基本上是需要读取一系列Client对象了,所以我们构建一个数组。

接下来我们遍历列表并且转发即可。

于是我们的Server改成了:

1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3import socket
4
5s = socket.socket()
6
7host = socket.gethostname()
8port = 1234
9s.bind((host, port))
10
11lists = []
12s.listen(5)
13
14while True:
15    c, addr = s.accept()
16    lists.append({'client': c, 'address': addr})
17    print lists
18    print 'Got connection from', addr
19    c.send('Thank you for connecting')
20    for client in lists:
21        msg = client['client'].recv(1024)
22        if msg:
23            print msg
24            for receiver in lists:
25                if receiver != client:
26                    receiver['client'].sendall(msg)
27    #word = raw_input('>')
28    #for c in lists:
29        #c['client'].sendall(word)
30
31for client in lists:
32    client['client'].close()
33

这样运行之后就发现改好了,但是触发条件很诡异,这是为什么,这就轮到了没说的阻塞还是不阻塞登场了,也是我们下一篇要说的,涉及到多线程的问题。

评论 (0)