基本原理
简单的说,客户端向服务器发送请求,以获得所需的服务,服务器就是接受客户端发送的请求,并根据请求的不同任务来向用户做出相应的应答,一般来说,客户端的数量是远远多于服务器的。
套接字
那么如何能保证服务器接收到每一个客户端的请求,并且无误地回应各个请求呢?这便需要服务器和客户端有一个通用的通信接口——套接字。套接字由主机和端口号来标志,他们的组合可以唯一标识网络上的每一个会话。主机是一个字符串,即IP地址(比如本地IP:127.0.0.1)或者域名(如nankai.edu.cn),端口号则是用于会话时的协商数字标识符,端口号是一个0-65535之间的整数,其中0-1023之间的端口号被预先分配给了更高层的标准协议。
实现
python的基本套接字接口是标准库的socket模块,是最底层的。
用一个功能多样的服务器和客户端小程序来实现本地的套接字层上(TCP协议)的通讯,可以实现客户端按下Ctrl+C结束服务,按下Ctrl+D结束输入,向服务器输入date,得到时间戳;输入os得到系统信息;输入ls,得到当前目录;输入ls+path,得到path下文件目录。
服务器代码
#!/usr/bin/env python from socket import * import os from time import ctime HOST = '' PORT = 21560 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: try: data = tcpCliSock.recv(BUFSIZ) print data,'',len(data) if not data: break if data == 'date': tcpCliSock.send('[%s] %s' %(ctime(),data)) continue if data == 'os': tcpCliSock.send('[%s]' %os.name) continue if data[0:2] == 'ls': if len(data) == 2: tcpCliSock.send('[%s]' %os.curdir) else: data_dir = data[3:len(data)] tcpCliSock.send('[%s]' %os.listdir(data_dir)) continue tcpCliSock.send('welcome') except Exception: break print addr,'connection closed' tcpCliSock.close() tcpSerSock.close()
- 第5-7行分别定义了主机(空意味着可以任意),端口号(任选一个大于1023且未被占用的即可),缓冲区大小(这里取1024B)
- – 第九行生成一个服务器套接字对象(AF_INET代表IP地址协议,SOCK_STREAM代表TCP传输协议)
- – 第十行将主机与端口号与生成的套接字绑定,也就是把套接字对象与某一地址关联起来(注意参数是元组)
- – 第11行设定可服务器监听的客户端数目为5
- – 外层while循环中第14行将接受客户端的请求,返回客户端套接字对象和其(地址,端口号)元组
- – 内层while循环中第18行将接收客户端发送的数据,并按照下面的if语句执行相应的功能
- – 这里的异常处理主要是解决客户端突然离线从而无法跳出内层循环的问题
- – 任何一个套接字对象需要在不再使用时销毁,如最后两行
客户端代码
#!/usr/bin/env python from socket import * HOST = '127.0.0.1' PORT = 21560 BUFSIZ = 1024 ADDR = (HOST,PORT) tcpCstmSock = socket(AF_INET,SOCK_STREAM) tcpCstmSock.connect_ex(ADDR) while True: try: data = '' while True: try: tp = raw_input('>') data = data + tp except EOFError: break except KeyboardInterrupt: break if not data: break tcpCstmSock.send(data) data = tcpCstmSock.recv(BUFSIZ) if not data: break print data tcpCstmSock.close()
- 第三行端口号设置为本地IP,也就是服务器的地址(毕竟服务器和客户端全都在本地)
- 第七行同样要建立套接字对象- 第八行连接服务器,指定的要连接的服务器IP地址和端口号
- 内层循环利用异常处理实现了按下Ctrl+D即结束输入
- 外层循环也利用异常处理实现了按下Ctrl+C即结束通讯(跳出外层循环,销毁客户端套接字对象)
- 22行表示将用户输入的字符串发送到服务器
- 23行表示接收服务器的发送回来的字符串信息
- 最后一行销毁客户端套接字对象
摸鱼堡版权所有丨如未注明,均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明转自:http://moyubao.net/coder/259/
转载请注明转自:http://moyubao.net/coder/259/