10.socket网络编程
套接字工作流程

先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。
Socket Families(地址簇)
socket.AF_UNIX unix本机进程间通信
socket.AF_INET IPV4
socket.AF_INET6 IPV6
Socket Types
socket.SOCK_STREAM #for tcp
socket.SOCK_DGRAM #for udp
Socket 参数
s.bind(address) 绑定(host,port)
s.listen(backlog) 开始监听传入连接。backlog指定在拒绝连接之前,可以挂起的最大连接数量
s.accept() 接受连接并返回(conn,address),其中conn是新的套接字对象,可以用来接收和发送数据。address是连接客户端的地址。
s.connect(address) address的格式为元组(hostname,port)
s.setblocking(bool) 是否阻塞(默认True),如果设置False,那么accept和recv时一旦无数据,则报错。
s.close() 关闭套接字
s.recv(bufsize) bufsize指定最多可以接收的数量
s.send(string) 将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。即:可能未将指定内容全部发送。
s.sendall(string) 将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。
内部通过递归调用send,将所有内容发送出去。
s.settimeout(timeout) 设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般,超时期应该在
刚创建套接字时设置,因为它们可能用于连接的操作(如 client 连接最多等待5s )
s.getpeername() 返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)
服务端
- 创建socket对象
- 绑定IP和端口 绑定 bind()
- 开始监听链接 监听 listen()
- 阻塞 , 等待客户端成功连接 阻塞 accept()
- 接收请求数据 接收 recv()
- 处理并发送请求数据 发送 send()
- 关闭 close()
客户端
- 创建socket对象
- 连接服务端 , 按照IP和端口连接 连接 connet()
- 发送请求数据 发送 send()
- 接收请求数据 接收 recv()
- 关闭 close()
简单socket
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 重用ip和端口 ,但其它client只是挂起状态。只有一个能交互
import socket
# 创建socket对象
sock = socket.socket()
# 绑定IP和端口,参数是一个元组(ip,port)
sock.bind(('localhost', 8080))
# 开始监听,最大挂起5个
sock.listen(5)
# 阻塞,等待连接
conn,addr = sock.accept()
# 接收请求数据,接收大小为1024字节
content = conn.recv(1024)
print(content.decode())
# 发送请求结果,必须以bytes类型
conn.send(b'jieshouwanbi')
# 关闭链接
conn.close()
s.server
import socket
# 创建socket对象
sock = socket.socket()
# 建立链接
sock.connect(('localhost', 8080))
# 发送请求数据,必须以bytes类型
sock.send(b"hello")
# 接收请求结果
content = sock.recv(1024)
print(content.decode())
# 关闭套接字
sock.close()
s.client
SSH
import socket ,os
server = socket.socket() #创建socket对象
server.bind(('localhost',9999) ) #绑定ip和port
server.listen() #开始监听 while True:
conn, addr = server.accept() #阻塞 等待连接
print("new conn:",addr)
while True:
print("等待新指令")
data = conn.recv(1024) #接收客户端发过来的命令
if not data:
break
print("执行指令:",data)
cmd_res = os.popen(data.decode()).read() #执行客户端发过来的命令,返回信息长度(接收字符串,执行结果也是字符串)
print("before send",len(cmd_res)) #信息的长度
if len(cmd_res) ==0:
cmd_res = "cmd has no output..." conn.send( str(len(cmd_res.encode())).encode("utf-8") ) #先发命令执行的结果信息大小给客户端
client_ack = conn.recv(1024) #防止粘包,客户端ack
conn.send(cmd_res.encode("utf-8")) #发送信息
print("send done") server.close()
server_ssh
import socket
client = socket.socket()
client.connect(('localhost',9999)) while True:
cmd = input(">>:").strip() #输入命令
if len(cmd) == 0: continue
client.send(cmd.encode("utf-8")) #发送命令给server端
cmd_res_size = client.recv(1024) #接受server端发过来的命令结果信息长度
print("命令结果大小:",cmd_res_size)
client.send("准备接受".encode('utf-8')) #防止粘包
received_size = 0 #已经接受数据的大小
received_data = b''
while received_size < int(cmd_res_size.decode()):
data = client.recv(1024) #只要小于,就一直接收
received_size += len(data) #每次收到的有可能小于1024,所以
必须用len判断
#print(data.decode())
received_data += data
else:
print("cmd res receive done...",received_size)
print(received_data.decode()) client.close()
client
ftp传文件
ftp server
1. 读取文件名
2. 检测文件是否存在
3. 打开文件
4. 检测文件大小
5. 发送文件大小给客户端
6. 等客户端确认
7. 开始边读边发数据
8. 发送md5
import socket ,os
server = socket.socket()
server.bind(('localhost',9999))
server.listen() while True:
conn, addr = server.accept()
print("new conn:",addr)
while True:
print("等待新指令")
data = conn.recv(1024)
if not data:
print("客户端已断开")
break
cmd,filename = data.decode().split()
print(filename)
if os.path.isfile(filename): #判断是否是文件
f = open(filename,"rb") #打开文件
file_size = os.stat(filename).st_size #文件大小
conn.send( str(file_size).encode() ) #send file size 防止粘包
conn.recv(1024) #wait for ack
for line in f:
conn.send(line) #开始发送
f.close()
print("send done") server.close()
ftp_server
import socket
import hashlib
client = socket.socket()
client.connect(('localhost', 9999)) while True:
cmd = input(">>:").strip()
if len(cmd) == 0: continue if cmd.startswith("get"): #判断是否以字符串‘get’ 开头
client.send(cmd.encode()) #把需要下载的文件发给server端
server_response = client.recv(1024) #接收server端发过来的文件大小
print("servr response:", server_response) #打印文件大小
client.send(b"ready to recv file") #防止粘包
file_total_size = int(server_response.decode())
received_size = 0 #已经接收的大小
filename = cmd.split()[1]
f = open(filename + ".new", "wb") #创建新文件 用于保存 while received_size < file_total_size:
if file_total_size - received_size > 1024: # 要收不止一次
size = 1024
else: # 最后一次了,剩多少收多少
size = file_total_size - received_size
print("last receive:", size) data = client.recv(size)
received_size += len(data)
f.write(data)
# print(file_total_size,received_size)
else:
print("file recv done", received_size, file_total_size)
f.close()
client.close()
ftp_client
import hashlib
import socket ,os,time
server = socket.socket()
server.bind(('localhost',9999))
server.listen()
while True:
conn, addr = server.accept()
print("new conn:",addr)
while True:
print("等待新指令")
data = conn.recv(1024)
if not data:
print("客户端已断开")
break
cmd,filename = data.decode().split()
print(filename)
if os.path.isfile(filename):
f = open(filename,"rb")
m = hashlib.md5()
file_size = os.stat(filename).st_size
conn.send( str(file_size).encode() ) #send file size
conn.recv(1024) #wait for ack
for line in f:
m.update(line)
conn.send(line)
print("file md5", m.hexdigest())
f.close()
conn.send(m.hexdigest().encode()) #send md5
print("send done") server.close()
md5_ftp_server
import socket
import hashlib
client = socket.socket()
client.connect(('localhost', 9999)) while True:
cmd = input(">>:").strip()
if len(cmd) == 0: continue
if cmd.startswith("get"):
client.send(cmd.encode())
server_response = client.recv(1024)
print("servr response:", server_response)
client.send(b"ready to recv file")
file_total_size = int(server_response.decode())
received_size = 0
filename = cmd.split()[1]
f = open(filename + ".new", "wb")
m = hashlib.md5() while received_size < file_total_size:
if file_total_size - received_size > 1024: # 要收不止一次
size = 1024
else: # 最后一次了,剩多少收多少
size = file_total_size - received_size
print("last receive:", size) data = client.recv(size)
received_size += len(data)
m.update(data)
f.write(data)
print(file_total_size,received_size)
else:
new_file_md5 = m.hexdigest()
print("file recv done", received_size, file_total_size)
f.close()
server_file_md5 = client.recv(1024)
print("server file md5:", server_file_md5)
print("client file md5:", new_file_md5) client.close()
md5_ftp_cli
10.socket网络编程的更多相关文章
- Python Socket 网络编程
Socket 是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于 Socket 来完成通信的,例如我们每天浏览网页.QQ ...
- Python之路【第七篇】python基础 之socket网络编程
本篇文章大部分借鉴 http://www.cnblogs.com/nulige/p/6235531.html python socket 网络编程 一.服务端和客户端 BS架构 (腾讯通软件:ser ...
- Socket网络编程--FTP客户端
Socket网络编程--FTP客户端(1)(Windows) 已经好久没有写过博客进行分享了.具体原因,在以后说. 这几天在了解FTP协议,准备任务是写一个FTP客户端程序.直接上干货了. 0.了解F ...
- Socket网络编程(2)--服务端实现
中秋了,首先祝大家中秋快乐,闲着无事在家整一个socket的聊天程序,有点仿QQ界面,就是瞎折腾,不知道最后是不是能将所有功能实现. 如果你对socket不了解,请看这篇文章:http://www.c ...
- 循序渐进Socket网络编程(多客户端、信息共享、文件传输)
循序渐进Socket网络编程(多客户端.信息共享.文件传输) 前言:在最近一个即将结束的项目中使用到了Socket编程,用于调用另一系统进行处理并返回数据.故把Socket的基础知识总结梳理一遍. 1 ...
- windows socket 网络编程
样例代码就在我的博客中,包含六个UDP和TCP发送接受的cpp文件,一个基于MFC的局域网聊天小工具project,和此小工具的全部执行时库.资源和执行程序.代码的压缩包位置是http://www.b ...
- SOCKET网络编程5
SOCKET网络编程快速上手(二)——细节问题(5)(完结篇) 6.Connect的使用方式 前面提到,connect发生EINTR错误时,是不能重新启动的.那怎么办呢,是关闭套接字还是直接退出进程呢 ...
- SOCKET网络编程细节问题(4)
SOCKET网络编程快速上手(二)——细节问题(4) 5.慢系统调用及EINTR 还记得前面readn和writen函数么?里面有个EINTR,现在就来谈谈这个,这个很重要. Linux世界有个叫信号 ...
- SOCKET网络编程细节问题3
SOCKET网络编程快速上手(二)——细节问题(3) 3.SIGPIPE问题 人怕牺牲,我们写的程序也一样,人有死不瞑目,程序又何尝不是?程序跑着跑着,突然就崩掉了.好一点的牺牲前告诉你些打印,差点的 ...
随机推荐
- Python自动化测试、性能测试成长路线图
Python自动化测试成长路线图 性能测试成长路线图
- linux 管理权限
linux 管理权限 linux 文件 权限 1.使用 ls -l 命令 执行结果如下(/var/log) : drwxr-x--- 2 root adm 4096 2013-08-07 11:03 ...
- scp的简单记忆方法
scp虽然只有把文见发送到远端和从远端copy文件俩功能,但是常常把俩功能的先写什么给计混了,所以我就用通俗的大白话给总结了下,十分容易记忆,这里给大家分享一下.scp 我们常用的两个功能: (1)把 ...
- 阶乘之和 输入n,计算S=1!+2!+3!+…+n!的末6位(不含前导0)。n≤10 6 ,n!表示 前n个正整数之积。
阶乘之和输入n,计算S=1!+2!+3!+…+n!的末6位(不含前导0).n≤10 6 ,n!表示前n个正整数之积.样例输入:10样例输出: package demo; import java.uti ...
- 1.12 dict 字典表
dict 字典表属于映射分类 dict的声明 >>> #dict类型 是 {}中包含若干个键值对 >>> d = dict() >>> d = { ...
- json字符串转换成json对象,json对象转换成字符串,值转换成字符串,字符串转成值
一.json相关概念 json,全称为javascript object notation,是一种轻量级的数据交互格式.采用完全独立于语言的文本格式,是一种理想的数据交换格式. 同时,json是jav ...
- 蚂蚁爬杆问题 UVA 10881
算法入门经典训练指南上的题. 这里有必要讲一下蚂蚁爬杆问题:每只蚂蚁都有一个初始方向,相撞会转向,关键就是相撞的处理,由于速度并不会改变,两只蚂蚁相撞,可以看做,两只蚂蚁穿过对方,继续沿原方向前进,经 ...
- Luogu P1596 [USACO10OCT]湖计数Lake Counting
题目描述 Due to recent rains, water has pooled in various places in Farmer John's field, which is repres ...
- Spring MVC处理(下周完善)
http://www.cnblogs.com/xiepeixing/p/4244574.html http://blog.csdn.net/kobejayandy/article/details/12 ...
- 转:20分钟教你使用hexo搭建github博客
注册Github账号 这里我们就不多讲了,小伙伴们可以点击这里,进入官网进行注册. 创建仓库 图片来自Github 登录账号后,在Github页面的右上方选择New repository进行仓库的创建 ...