Python Socket编程

Socket套接字

前言



socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,对于文件用【打开】【读写】【关闭】模式来操作。
socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)

- socket和file的区别

1. file模块是针对某个指定文件进行【打开】【读写】【关闭】

2. socket模块是针对 服务器端 和 客户端 Socket 进行【打开】【读写】【关闭】

下面我们通过几种不同方式来实现时间戳服务器端和客户端:TCPUDPSocketServer TCPTwisted Reactor TCP

TCP时间戳服务

TCP服务器端

TCP服务器端设计方式伪代码

1
2
3
4
5
6
7
8
9
ss = socket()               # 创建服务器套接字
ss.bind() # 套接字与地址绑定
ss.listen() # 监听连接
inf_loop: # 服务器无限循环
cs = ss.accept() # 接受客户端连接
comm_loop: # 通信循环
cs.recv()/cs.send() # 对话(接受/发送)
cs.close() # 关闭客户端套接字
ss.close() # 关闭服务器套接字(可选)

创建TCP时间戳服务器

TCP时间戳服务器(tsTserv.py)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/usr/bin/env python
# coding=utf-8

"""
创建一个TCP服务器,它接受来自客户端的消息,然后将消息加上时间前缀并发送回客户端
"""


from socket import *
from time import ctime


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

tcpSerSock = socket(AF_INET, SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)

while True:
print("waiting for connection...")
tcpCliSock, addr = tcpSerSock.accept()
print("...connected from ", addr)

while True:
data = tcpCliSock.recv(BUFSIZ)
if not data:
break
tcpCliSock.send(bytes('[%s] %s' % (ctime(), data.decode('utf-8')),'utf-8'))
tcpCliSock.close()

tcpSerSock.close()

TCP客户端

客户端伪代码

1
2
3
4
5
cs = socket()           # 创建客户端套接字
cs.connect() # 尝试连接服务器
comm_loop: # 通信循环
cs.send()/cs.recv() # 对话(发送/接收)
cs.close() # 关闭客户端套接字

创建TCP时间戳客户端

TCP时间戳客户端(tsTclnt.py)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/usr/bin/env python
# coding=utf-8

"""
"""

from socket import *

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

tcpCliSock = socket(AF_INET, SOCK_STREAM)
tcpCliSock.connect(ADDR)

while True:
data = input('> ')
if not data:
break
tcpCliSock.send(bytes(data,'utf-8'))
data = tcpCliSock.recv(BUFSIZ)
if not data:
break
print(data.decode('utf-8'))


tcpCliSock.close()

执行TCP服务器和客户端

  • 服务器端:
1
2
3
4
$ python tsTserv.py
waiting for connection...
...connected from ('127.0.0.1', 28182)
waiting for connection
  • 客户端
1
2
3
4
5
6
$ python tsTclnt.py
> Hi
[Wed Oct 24 10:39:43 2018] Hi
> I'm Jack
[Wed Oct 24 10:39:47 2018] I'm Jack
>

UDP时间戳服务器

UDP服务器端

TCP服务器端设计方式伪代码

1
2
3
4
5
ss = socket()                   # 创建服务器套接字
ss.bind() # 绑定服务器套接字
inf_loop: # 服务器无限循环
ss.recvfrom()/ss.sendto() # 接收/发送
ss.close() # 关闭服务器套接字

创建UDP服务器

UDP时间戳服务器(tsUserv.py)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/bin/env python
# coding=utf-8
"""
UDP TimeStamp server
"""

from socket import *
from time import ctime

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

udpSerSock = socket(AF_INET, SOCK_DGRAM)
udpSerSock.bind(ADDR)

while True:
print("wating for message...")
data, addr = udpSerSock.recvfrom(BUFSIZ)
udpSerSock.sendto(bytes('[%s] %s' %
(ctime(), data.decode('utf-8')), 'utf-8'), addr)
print("...received from and returned to:", addr)

udpSerSock.close()

UDP客户端

UDP客户端端设计方式伪代码

1
2
3
4
cs = socket()                   # 创建客户端套接字
comm_loop: # 通信循环
cs.sendto()/cs.recvfrom() # 对话(发送接收)
cs.close() # 关闭客户端套接字

创建UDP客户端

UDP时间戳客户端(tsUclnt.py)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/usr/bin/env python
# codin=utf-8
"""
UDP TimeStamp Client
"""

from socket import *


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

udpSerSock = socket(AF_INET, SOCK_DGRAM)

while True:
data = input('> ')
if not data:
break
udpSerSock.sendto(bytes(data,'utf-8'), ADDR)
data, ADDR = udpSerSock.recvfrom(BUFSIZ)
if not data:
break
print(data.decode('utf-8'))

udpSerSock.close()

SocketServer时间戳

服务器端

SocketServer时间戳TCP服务器(tsTservSS.py)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#!/usr/bin/env python
# coding=utf-8

"""
SocketServer时间戳TCP服务器
使用SocketServer类、TCPServer和StreamRequestHandler
分叉,多线程
windows不支持分叉
"""


from socketserver import (TCPServer as TCP, StreamRequestHandler as SRH,
ForkingMixIn as FMI, ThreadingMixIn as TMI)

from time import ctime

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


class FServer(FMI, TCP):
pass

class TServer(TMI, TCP):
pass

class MyRequestHandler(SRH):
def handle(self):
print("...connected from:", self.client_address)
self.wfile.write(
("[%s] %s" % (ctime(), self.rfile.readline().decode('utf-8'))).encode('utf-8'))


tcpServ = TServer(ADDR, MyRequestHandler) # TCP, FSever, TServer
print("waiting for connection...")

tcpServ.serve_forever()

客户端

SocketServer时间戳TCP客户端(tsTclntSS.py)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/usr/bin/env python
# coding=utf-8

"""
SocketServer时间戳TCP客户端

"""


from socket import *

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

while True:
tcpCliSock = socket(AF_INET, SOCK_STREAM)
tcpCliSock.connect(ADDR)
data = input('> ')
if not data:
break
tcpCliSock.send(("%s\r\n" % data).encode('utf-8'))
data = tcpCliSock.recv(BUFSIZ).decode('utf-8')
if not data:
break
print(data.strip())
tcpCliSock.close()

Twisted Reactor TCP时间戳

服务器端

Twisted Reactor时间戳TCP服务器(tsTservTW.py)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/env python
# coding=utf-8

"""
Twisted Reactor时间戳TCP服务器,使用了Twisted Internet类
"""

from twisted.internet import protocol, reactor
from time import ctime

PORT = 21567

class TSServProtocol(protocol.Protocol):
def connectionMade(self):
clnt = self.clnt = self.transport.getPeer().host
print("...connected from:", clnt)
def dataReceived(self, data):
self.transport.write(("[%s] %s" % (ctime(), data.decode('utf-8'))).encode("utf-8"))

factory = protocol.Factory()
factory.protocol = TSServProtocol
print("waiting fro connection...")
reactor.listenTCP(PORT, factory)
reactor.run()

客户端

Twisted Reactor时间戳TCP客户端(tsTclntTW.py)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/usr/bin/env python
# coding=utf-8

"""
Twisted Reactor时间戳TCP客户端
"""

from twisted.internet import protocol, reactor

PORT = 21567
HOST = 'localhost'

class TSClntProtocol(protocol.Protocol):
def sendData(self):
data = input('> ')
if data:
print("...sending %s..." % data)
self.transport.write(data.encode('utf-8'))
else:
self.transport.loseConnection()

def connectionMade(self):
self.sendData()

def dataReceived(self, data):
print(data.decode())
self.sendData()

class TSClntFactory(protocol.ClientFactory):
protocol = TSClntProtocol
clientConnectionLost = clientConnectionFailed = lambda self, connector, reason: reactor.stop()

reactor.connectTCP(HOST, PORT, TSClntFactory())
reactor.run()

小结

我们用几种方式实现了一个时间戳服务器和客户端,下次我们将学习IO多路复用及python下的select模块

-------------阅读完毕吐槽一番吧~-------------
0%