1. 面向连接的套接字和无连接的套接字之间的区别是什么?
- 套接字是计算机网络数据结构,套接字最初是为同一主机上的应用程序所创建,使得主机上的不同应用程序可以相互通信,这就是所谓的进程间通信(Inter Process Communication,IPC)
面向连接的套接字 | 无连接的套接字 |
---|---|
在通信之前必须建立连接 | 在通信之前不需要建立连接 |
序列化的,可靠的不重复的数据交付 | 无法保证顺序性,可靠性或重复性,减少以一定的开销 |
没有记录边界 | 保存了记录边界 |
每条信息可以拆分成多个片段,并且每一个消息片段都能确保到达目的地,然后将他么按顺序组合在一起。 | 消息是以整体发送的。 |
传输控制协议(TCP) | 用户数据协议(UDP) |
2. 客户端/服务器架构
- 服务器就是一系列硬件或软件,为一个或多个客户端(服务的用户)提供所需的“服务”。其存在的目的就是等待客户端的请求,并响应他们(提供服务),然后等待更多的请求。
3. TCP和UDP之中,哪种类型的服务器接收连接,并将他们转换到独立的套接字进行客户端通信
TCP
4. 更新TCP(tsTclnt.py)和UDP(tsUclnt.py)客户端,以使得服务器名称无须硬编码到应用程序中。
if __name__ == '__main__':
opts, args = getopt.getopt(sys.argv[1:],'',['host=','port='])
for op, value in opts:
if op == '--host':
HOST = value
elif op == '--port':
PORT = value
在程序中加入这段代码,可以通过输入命令来进行指定的host和port
5. 编写TCP客户端/服务器程序,使得服务器能够识别以下命令:
- date 服务器返回当前日期/时间戳,即time.ctime()
- os 获取操作系统信息(os.name)
- ls 列出当前目录文件清单(提示:os.listdir()列出一个目录,os.curdir()是当前目录)
tcp_server.py(服务器端代码)
import socket
from time import ctime
import os
import re
HOST = ''
PORT = 50006
ADDR = (HOST, PORT)
#获取指定路径的文件列表,默认为当前文件列表
def list_dir(path = os.curdir):
files = os.listdir(path)
filenames = []
for file in files:
filenames.append(file)
return '\n'.join(filenames)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind(ADDR)
s.listen(5)
while True:
conn, addr = s.accept()
with conn:
print('Connected by', addr)
while True:
data = conn.recv(1024)
s_data = ''
if not data: break
data = data.decode('utf-8')
#判断指令为time
if data == 'time':
s_data = '[%s]'%ctime()
#判断指令为os
elif data == 'os':
s_data = '[%s]'%os.name
else:
#判断指令为ls
if data == 'ls':
s_data = list_dir()
else:
#判断指令为ls path
patt = 'ls\s([^\s]+)'
m = re.match(patt,data)
if m:
path = m.group(1)
if os.path.exists(path):
s_data = list_dir(path)
else:
s_data = 'not exist path'
else:
s_data = 'this is no order' + data
conn.send(s_data.encode('utf-8'))
tcp_clnt.py(客户端代码)
import socket
HOST = 'localhost'
PORT = 50006
ADDR = (HOST, PORT)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect(ADDR)
while True:
data = input('>>> ')
if not data:break
s.send(data.encode('utf-8'))
data = s.recv(1024)
if not data:break
data = data.decode('utf-8')
print(data)
6. 半双工聊天
hdserver.py(半双工聊天服务器)
from socket import *
HOST = ''
PORT = 50006
BUFSIZE = 1024
ADDR = (HOST, PORT)
with socket(AF_INET, SOCK_STREAM) as s:
s.bind(ADDR)
s.listen(5)
while True:
conn, addr = s.accept()
with conn:
print('connected by ',addr)
while True:
data = conn.recv(BUFSIZE)
if not data:break
print('from:',data.decode('utf-8'))
data = input('to: ')
if not data:break
conn.send(data.encode('utf-8'))
hdclnt.py(半双工聊天客户端)
from socket import *
HOST = 'localhost'
POST = 50006
BUFSIZE = 1024
ADDR = (HOST, POST)
with socket(AF_INET, SOCK_STREAM) as s:
s.connect(ADDR)
while True:
data = input('to: ')
if not data:break
s.send(data.encode('utf-8'))
data = s.recv(BUFSIZE)
print('from: ',(data.decode('utf-8')))
7. 全双工聊天
fdserver.py(全双工服务器)
from socket import *
from select import *
import sys
HOST = ''
PORT = 50007
BUFSIZE = 1024
ADDR = (HOST, PORT)
with socket(AF_INET, SOCK_STREAM) as tcp_server:
tcp_server.bind(ADDR)
tcp_server.listen(5)
inpu = [tcp_server, sys.stdin]
while True:
conn, addr = tcp_server.accept()
inpu.append(conn)
while True:
r_list, w_list,e_list = select(inpu,[],[])
for s in r_list:
if s == conn:
data = conn.recv(BUFSIZE)
if not data: break
print(data.decode('utf-8'))
else:
data = input('>>> ')
if not data: break
conn.send(data.encode('utf-8'))
fdclnt.py(全双工聊天客户端)
from socket import *
from select import *
import sys
HOST = 'localhost'
POST = 50007
BUFSIZE = 1024
ADDR = (HOST, POST)
with socket(AF_INET, SOCK_STREAM) as tcp_clnt:
tcp_clnt.connect(ADDR)
inpu = [tcp_clnt,sys.stdin]
while True:
r_list, w_list, e_list = select(inpu,[],[])
for s in r_list:
if s == tcp_clnt:
data = tcp_clnt.recv(BUFSIZE)
if not data: break
print((data.decode('utf-8')))
else:
data = input('>>> ')
if not data:break
tcp_clnt.send(data.encode('utf-8'))
8. 多用户全双工聊天
mfd_server(多用户全双工聊天服务器端)
from socket import *
import threading
HOST = ''
PORT = 21568
BUFSIZE = 1024
ADDR = (HOST, PORT)
conns = []
#当收到消息时,向其他用户发送消息
def deal_conn(conn):
while True:
data = conn.recv(BUFSIZE)
if not data:break
for c in conns:
if c != conn:
c.send(data)
with socket(AF_INET, SOCK_STREAM) as server:
server.bind(ADDR)
server.listen(10)
while True:
conn, addr = server.accept()
#向其他用户发送进入聊天室欢迎语
if conn not in conns:
for c in conns:
greet = '欢迎%s来到我们的聊天室!' %str(addr)
c.send(greet.encode('utf-8'))
conns.append(conn)
t = threading.Thread(target=deal_conn,args=(conn,))
t.start()
mfd_clnt.py(多用户全双工聊天客户端)
from socket import *
from select import *
import sys
HOST = 'localhost'
POST = 21568
BUFSIZE = 1024
ADDR = (HOST, POST)
with socket(AF_INET, SOCK_STREAM) as server:
server.connect(ADDR)
inpu = [server,sys.stdin]
while True:
r_list, w_list, e_list = select(inpu,[],[])
for s in r_list:
if s == server:
data = server.recv(BUFSIZE)
if not data: break
print((data.decode('utf-8')))
else:
data = input('>>> ')
if not data:break
server.send(data.encode('utf-8'))
9. 多用户、多房间、全双工聊天
####### mmfd_server(多用户多房间全双工聊天)
from socket import *
import re
import threading
HOST = ''
PORT = 21568
BUFSIZE = 1024
ADDR = (HOST, PORT)
rooms = {}
conns = {}
REFUSE = '对方正在聊天,您的请求拒绝连接'.encode('utf-8')
WAITING = '请等待对方上线'.encode('utf-8')
INPUT_ERROR = '您的输入有误'.encode('utf-8')
def deal_conn(name):
while True:
conn_from = conns[name]
data = conn_from.recv(BUFSIZE)
if not data:break
if rooms[name] in conns:
conn_to = conns[rooms[name]]
conn_to.send(data)
else:
conn_from.send(WAITING)
with socket(AF_INET, SOCK_STREAM) as server:
server.bind(ADDR)
server.listen(10)
while True:
conn, addr = server.accept()
settings = conn.recv(BUFSIZE)
patt = r'name:(.+)\sto:(.+)'
m = re.match(patt,settings.decode('utf-8'))
if not m:conn.send(INPUT_ERROR)
name = m.group(1)
if name not in conns:
conns[name] = conn
to = m.group(2)
if name not in rooms and to not in rooms:
rooms[name] = to
rooms[to] = name
elif name in rooms and rooms[name] != to:
del conns[name]
if name in rooms:
del rooms[name]
conn.send(REFUSE)
conn.close()
t = threading.Thread(target=deal_conn,args=(name,))
t.start()
mmfd_clnt(多用户多房间全双工聊天)
from socket import *
from select import *
import sys
HOST = 'localhost'
POST = 21568
BUFSIZE = 1024
ADDR = (HOST, POST)
with socket(AF_INET, SOCK_STREAM) as server:
server.connect(ADDR)
inpu = [server,sys.stdin]
print("请输入你的姓名和对方的姓名(格式name:你的姓名 to:对方姓名)")
data = input('')
server.send(data.encode('utf-8'))
while True:
r_list, w_list, e_list = select(inpu,[],[])
for s in r_list:
if s == server:
data = server.recv(BUFSIZE)
if not data: break
print((data.decode('utf-8')))
else:
data = input('>>> ')
if not data:break
server.send(data.encode('utf-8'))