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

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

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

官网Demo有云:

# Echo server program
import socket

HOST = ''                 # Symbolic name meaning all available interfaces
PORT = 50007              # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print 'Connected by', addr
while 1:
    data = conn.recv(1024)
    if not data: break
    conn.sendall(data)
conn.close()
# Echo client program
import socket

HOST = 'daring.cwi.nl'    # The remote host
PORT = 50007              # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall('Hello, world')
data = s.recv(1024)
s.close()
print 'Received', repr(data)

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

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

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

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

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

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

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

import socket

s = socket.socket()

host = socket.gethostname()
port = 1234

s.connect((host, port))
print s.recv(1024)
s.sendall('Hello World')
while 1:
    word = raw_input('>')
    s.sendall(word)
    print s.recv(1024)

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

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

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

于是我们的Server改成了:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket

s = socket.socket()

host = socket.gethostname()
port = 1234
s.bind((host, port))

lists = []
s.listen(5)

while True:
    c, addr = s.accept()
    lists.append({'client': c, 'address': addr})
    print lists
    print 'Got connection from', addr
    c.send('Thank you for connecting')
    for client in lists:
        msg = client['client'].recv(1024)
        if msg:
            print msg
            for receiver in lists:
                if receiver != client:
                    receiver['client'].sendall(msg)
    #word = raw_input('>')
    #for c in lists:
        #c['client'].sendall(word)

for client in lists:
    client['client'].close()

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

植入部分

如果您觉得文章不错,可以通过赞助支持我。

如果您不希望打赏,也可以通过关闭广告屏蔽插件的形式帮助网站运作。

标签: 成品, 源码, 知识, 代码段, 语法

添加新评论