Day9 网络编程
OSI(Open System Interconnect),即开放式系统互联。
ISO(International Standards Organization)国际标准化组织
OSI七层模型:
TCP/IP协议:
TCP三次握手:
TCP四次挥手:
TCP通信:
模拟简单的客户端-服务器TCP通信
socket_server.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: wanghuafeng import socket
ip_port = ('127.0.0.1', 9999)
#买手机
s = socket.socket()
#买手机卡,bind中的参数为元祖
s.bind(ip_port)
#开机
s.listen(5)
#等待电话,conn为通信链路
conn, addr = s.accept()
#收消息,1024--代表字节
recv_data = conn.recv(1024)
print(str(recv_data, encoding='utf-8'))
#发消息
send_data = recv_data.upper()
conn.send(send_data)
#挂电话
conn.close()
socket_client.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: wanghuafeng import socket
ip_port = ('127.0.0.1', 9999)
#买手机
sk = socket.socket()
#拨号
sk.connect(ip_port)
#发消息
send_data = input(">>>: ").strip()
sk.send(bytes(send_data, encoding='utf-8'))
#收消息
recv_data = sk.recv(1024)
print(recv_data)
#挂电话
sk.close()
UDP通信
# 服务端
import socketip_port = ('127.0.0.1',9999)
sk = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0)
sk.bind(ip_port)
while True:
data,(host,port) = sk.recvfrom(1024)print(data,host,port)
sk.sendto(bytes('ok', encoding='utf-8'), (host,port))
#客户端
import socket
ip_port = ('127.0.0.1',9999)
sk = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0)
while True:inp = input('数据:').strip()
if inp == 'exit':
break
sk.sendto(bytes(inp, encoding='utf-8'),ip_port)
data = sk.recvfrom(1024)
print(data)
sk.close()
更多功能
sk.bind(address)
s.bind(address) 将套接字绑定到地址。address地址的格式取决于地址族。在AF_INET下,以元组(host,port)的形式表示地址。
sk.listen(backlog)
开始监听传入连接。backlog指定在拒绝连接之前,可以挂起的最大连接数量。
backlog等于5,表示内核已经接到了连接请求,但服务器还没有调用accept进行处理的连接个数最大为5
这个值不能无限大,因为要在内核中维护连接队列sk.setblocking(bool)
是否阻塞(默认True),如果设置False,那么accept和recv时一旦无数据,则报错。
sk.accept()
接受连接并返回(conn,address),其中conn是新的套接字对象,可以用来接收和发送数据。address是连接客户端的地址。
接收TCP 客户的连接(阻塞式)等待连接的到来
sk.connect(address)
连接到address处的套接字。一般,address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。
sk.connect_ex(address)
同上,只不过会有返回值,连接成功时返回 0 ,连接失败时候返回编码,例如:10061
sk.close()
关闭套接字
sk.recv(bufsize[,flag])
接受套接字的数据。数据以字符串形式返回,bufsize指定最多可以接收的数量。flag提供有关消息的其他信息,通常可以忽略。
sk.recvfrom(bufsize[.flag])
与recv()类似,但返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。
sk.send(string[,flag])
将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。即:可能未将指定内容全部发送。
sk.sendall(string[,flag])
将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。
内部通过递归调用send,将所有内容发送出去。
sk.sendto(string[,flag],address)
将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。该函数主要用于UDP协议。
sk.settimeout(timeout)
设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如 client 连接最多等待5s )
sk.getpeername()
返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。
sk.getsockname()
返回套接字自己的地址。通常是一个元组(ipaddr,port)
sk.fileno()
套接字的文件描述符
循环发送消息
socket_server.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: wanghuafeng import socket
ip_port = ('127.0.0.1', 9999)
#买手机
s = socket.socket()
#买手机卡,bind中的参数为元祖
s.bind(ip_port)
#开机
s.listen(5)
#等待电话,conn为通信链路
conn, addr = s.accept()
while True:
try:
#收消息,1024--代表字节
recv_data = conn.recv(1024)
print(str(recv_data, encoding='utf-8'))
if str(recv_data, encoding='utf-8') == 'exit':break
#发消息
send_data = recv_data.upper()
conn.send(send_data)
except Exception:
break
#挂电话
conn.close()
socket_client.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: wanghuafeng import socket
ip_port = ('127.0.0.1', 9999)
#买手机
sk = socket.socket()
#拨号
sk.connect(ip_port)
#发消息
while True:
send_data = input(">>>: ").strip()
if len(send_data) == 0:continue
sk.send(bytes(send_data, encoding='utf-8'))
if send_data == 'exit':break
#收消息
recv_data = sk.recv(1024)
print(recv_data)
#挂电话
sk.close()
发送windows命令并返回结果
socket_server.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: wanghuafeng import socket
import subprocess
ip_port = ('127.0.0.1', 9999)
#买手机
s = socket.socket()
#买手机卡,bind中的参数为元祖
s.bind(ip_port)
#开机
s.listen(5)
#等待电话,conn为通信链路
#重复接收多个连接
while True:
conn, addr = s.accept()
while True:
try:
#收消息,1024--代表字节
recv_data = conn.recv(1024)
print(str(recv_data, encoding='utf8'))
if str(recv_data, encoding='utf8') == 'exit':break
#发消息
# 在Windows服务器获取命令
p = subprocess.Popen(str(recv_data, encoding='utf8'), shell=True, stdout=subprocess.PIPE)
res = p.stdout.read()
if len(res) == 0:
send_data = "cmd error"
else:
send_data = str(res, encoding='gbk')
print(send_data)
conn.send(bytes(send_data, encoding='utf8'))
except Exception:
break
#挂电话
conn.close()
socket_client.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: wanghuafeng import socket
ip_port = ('127.0.0.1', 9999)
#买手机
sk = socket.socket()
#拨号
sk.connect(ip_port)
#发消息
while True:
send_data = input(">>>: ").strip()
if len(send_data) == 0:continue
sk.send(bytes(send_data, encoding='utf8'))
if send_data == 'exit':break
#收消息
recv_data = sk.recv(1024)
print(str(recv_data, encoding='utf8'))
#挂电话
sk.close()
解决粘包
socket_server.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: wanghuafeng import socket
import subprocess #导入执行命令模块
ip_port = ('127.0.0.1', 9999) #定义IP和端口的元组
#买手机
s = socket.socket() #绑定协议,生成套接字
#买手机卡,bind中的参数为元祖
s.bind(ip_port) #绑定IP+协议+端口,用来唯一标识一个进程,ip_port必须是元组格式
#开机
s.listen(5) #定义最大可以挂起链接数
#等待电话,conn为通信链路
#重复接收多个连接
while True: #用来重复接收新的链接
conn, addr = s.accept() #接收客户端链接请求,返回conn(相当于通信信道,addr是客户端IP+Port)
while True: #用于基于一个链接重复收发消息
try: #捕捉客户端异常关闭(ctrl+c)
#收消息,1024--代表字节
recv_data = conn.recv(1024) #收消息,阻塞
if len(recv_data) == 0:break #客户端如果退出,服务端将收到空消息,退出
if str(recv_data, encoding='utf8') == 'exit':break #客户端发送exit消息,表示退出,服务端将退出
#发消息
# 在Windows服务器获取命令,并执行命令,Windows平台标准输出是gbk编码需要转换
p = subprocess.Popen(str(recv_data, encoding='utf8'), shell=True, stdout=subprocess.PIPE)
res = p.stdout.read() #获取标准输出
if len(res) == 0: #执行错误命令,标准输出为空
send_data = "cmd error"
else:
send_data = str(res, encoding='gbk') #执行ok,字符编码转换,gbk-->str-->utf8字节
send_data = bytes(send_data, encoding='utf8') # 解决粘包问题
#准备发送之前,先发送‘Ready|内容长度’
ready_tag = 'Ready|%s' %len(send_data)
conn.send(bytes(ready_tag, encoding='utf8'))
#得到客户端返回‘Start’表示客户端已经接收到‘Ready|内容长度’
feedback = conn.recv(1024) #Start
#接收的内容为bytes类型,需要转换为str类型
feedback = str(feedback, encoding='utf8')
if feedback.startswith('Start'):
conn.send(send_data) #发送命令执行结果
except Exception:
break
#挂电话
conn.close()
socket_client.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: wanghuafeng import socket
ip_port = ('127.0.0.1', 9999)
#买手机
sk = socket.socket()
#拨号
sk.connect(ip_port) #连接服务端,若服务端有一个已经存在的链接,则连接挂起
#发消息
while True: #基于connect建立的链接来循环发送消息
send_data = input(">>>: ").strip()
if len(send_data) == 0:continue
sk.send(bytes(send_data, encoding='utf8'))
if send_data == 'exit':break #解决粘包问题
#接收消息,其实是为了得到‘Ready|内容长度’
ready_tag = sk.recv(1024)
ready_tag = str(ready_tag, encoding='utf8')
#收到‘Ready|内容长度’
if ready_tag.startswith("Ready"):
#获取待接收数据的长度
msg_size = int(ready_tag.split('|')[-1])
#准备一个‘Start’
start_tag = 'Start'
#发送一个‘Start’消息,通知服务端可以发送消息了
sk.send(bytes(start_tag, encoding='utf8')) recv_size = 0
recv_msg = b''
while recv_size < msg_size:
recv_data = sk.recv(1024)
recv_msg += recv_data
recv_size += len(recv_data)
print('MSG SIZE %s RECV SIZE %s' % (msg_size, recv_size))
print(str(recv_msg, encoding='utf8'))
#挂电话
sk.close()
socketserver解决粘包问题
import socketserver
import subprocessclass Myserver(socketserver.BaseRequestHandler):
def handle(self):while True:
conn=self.request
conn.sendall(bytes("欢迎登录","utf8"))
while True:
client_bytes=conn.recv(1024)
if not client_bytes:break
client_str=str(client_bytes,"utf8")
print(client_str)
command=client_str
result_str=subprocess.getoutput(command)
result_bytes = bytes(result_str,encoding='utf8')info_str="info|%d"%len(result_bytes)
conn.sendall(bytes(info_str,"utf8"))
# conn.recv(1024)
conn.sendall(result_bytes)
conn.close()
if __name__=="__main__":
server=socketserver.ThreadingTCPServer(("127.0.0.1",9998),Myserver)server.serve_forever()
#####################################client
import socket
ip_port=("127.0.0.1",9998)
sk=socket.socket()
sk.connect(ip_port)print("客户端启动...")
print(str(sk.recv(1024),"utf8"))
while True:
inp=input("please input:").strip()sk.sendall(bytes(inp,"utf8"))
basic_info_bytes=sk.recv(1024)
print(str(basic_info_bytes,"utf8"))
# sk.send(bytes('ok','utf8'))
result_length=int(str(basic_info_bytes,"utf8").split("|")[1])
print(result_length)
has_received=0content_bytes=bytes()
while has_received<result_length:
fetch_bytes=sk.recv(1024)
has_received+=len(fetch_bytes)
content_bytes+=fetch_bytes
cmd_result=str(content_bytes,"utf8")
print(cmd_result)
sk.close()
实现简单FTP功能
ftp_server.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
#Author:WangHuafeng import socketserver
import subprocess
import json class MyServer(socketserver.BaseRequestHandler):
def handle(self):
self.request.sendall(bytes("欢迎使用Python Server!", encoding='utf-8'))
while True:
data = self.request.recv(1024)
if len(data) == 0:break
print('data', data)
print("[%s] says:%s" % (self.client_address, data.decode()))
task_data = json.loads(data.decode())
task_action = task_data.get('action')
if hasattr(self, 'task_%s' % task_action):
func = getattr(self, 'task_%s' % task_action)
func(task_data)
else:
print('task action is not supported', task_action) def task_put(self, *args, *kwargs):
print("---put", args, kwargs)
filesize = args[0].get('file_size')
filename = args[0].get('filename')
server_response = {'status':200}
self.request.send(bytes(json.dumps(server_response), encoding='utf-8'))
recv_size = 0
with open(filename, 'wb') as f:
while recv_size < filesize:
data = self.request.recv(4096)
f.write(data)
recv_size += len(data)
print("file recv sucess") if __name__ == '__main__':
server = socketserver.ThreadingTCPServer(('192.168.6.130', 8999), MyServer)
server.serve_forever()
ftp_client.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-# Author: wanghuafeng
import socket
import os, json
ip_port = ('192.168.6.130', 8999)
sk = socket.socket()
sk.connect(ip_port)
welcome_msg = sk.recv(1024)
while True:
send_data = input(">>>: ").strip()if len(send_data) == 0:continue
cmd_list = send_data.split()
if len(cmd_list) < 2:continue #ftp命令put /usr/bin/file.txt
task_type = cmd_list[0]
if task_type == 'put':
abs_filepath = cmd_list[1]
if os.path.isfile(abs_filepath):
#MD5,留着
file_size = os.stat(abs_filepath).st_size
file_name = abs_filepath.split('\\')[-1]
print('file:%s size:%s' % (abs_filepath, file_size))
msg_data = {'action':'put', 'filename':file_name, 'file_size':file_size}
sk.send(bytes(json.dumps(msg_data), encoding='utf-8'))
server_confirmation_msg = sk.recv(1024)
confirm_data = json.loads(server_confirmation_msg.decode())
if confirm_data['status'] == 200:
print('start sending file', file_name)
with open(abs_filepath, 'rb') as f:for line in f:
sk.send(line)
print("send file done")
else:
print("\033[31;1mfile [%s] is not exist\033[0m" % abs_filepath)
else:
print("doesn't support task type", task_type)
continue
#sk.send(bytes(send_data, encoding='utf8'))
recv_data = sk.recv(1024)
print(str(recv_data, encoding='utf-8'))
sk.close()
Day9 网络编程的更多相关文章
- 第九章:Python の 网络编程基础(一)
本課主題 何为TCP/IP协议 初认识什么是网络编程 网络编程中的 "粘包" 自定义 MySocket 类 本周作业 何为TCP/IP 协议 TCP/IP协议是主机接入互网以及接入 ...
- Python基础-week07 Socket网络编程
一 客户端/服务器架构 1.定义 又称为C/S架构,S 指的是Server(服务端软件),C指的是Client(客户端软件) 本章的中点就是教大写写一个c/s架构的软件,实现服务端软件和客户端软件基于 ...
- 猫哥网络编程系列:HTTP PEM 万能调试法
注:本文内容较长且细节较多,建议先收藏再阅读,原文将在 Github 上维护与更新. 在 HTTP 接口开发与调试过程中,我们经常遇到以下类似的问题: 为什么本地环境接口可以调用成功,但放到手机上就跑 ...
- python select网络编程详细介绍
刚看了反应堆模式的原理,特意复习了socket编程,本文主要介绍python的基本socket使用和select使用,主要用于了解socket通信过程 一.socket模块 socket - Low- ...
- Linux Socket 网络编程
Linux下的网络编程指的是socket套接字编程,入门比较简单.在学校里学过一些皮毛,平时就是自学玩,没有见识过真正的socket编程大程序,比较遗憾.总感觉每次看的时候都有收获,但是每次看完了之后 ...
- 猫哥网络编程系列:详解 BAT 面试题
从产品上线前的接口开发和调试,到上线后的 bug 定位.性能优化,网络编程知识贯穿着一个互联网产品的整个生命周期.不论你是前后端的开发岗位,还是 SQA.运维等其他技术岗位,掌握网络编程知识均是岗位的 ...
- 浅谈C#网络编程(一)
阅读目录: 基础 Socket编程 多线程并发 阻塞式同步IO 基础 在现今软件开发中,网络编程是非常重要的一部分,本文简要介绍下网络编程的概念和实践. Socket是一种网络编程接口,它是对传输层T ...
- C++11网络编程
Handy是一个简洁优雅的C++11网络库,适用于linux与Mac平台.十行代码即可完成一个完整的网络服务器. 下面是echo服务器的代码: #include <handy/handy.h&g ...
- Java - 网络编程
Java的网络编程学习,关于计算机基础的学习参考:计算机网络基础学习 - sqh. 参考:
随机推荐
- heX:用HTML5和Node.JS开发桌面应用
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...
- 读完了csapp(中文名:深入理解计算机系统)
上个星期最终把csapp看完了. 我买的是中文版的,由于除了貌似评价不错以外,由于涉及到些自己不了解的底层东西,怕是看英文会云里雾里.如今看来,大概不能算是个长处,可是的确可以加快我的看书速度,否则一 ...
- android 98 MediaPlayer+SurfaceView播放视频
package com.itheima.videoplayer; import java.io.IOException; import android.media.MediaPlayer; impor ...
- android 模拟器定在了任务栏出不来了
系统 任务栏上显示了正在运行的模拟器,但是点击它,始终看不到模拟器显示出来.用Alt + Tab 切换也不行 按照网上的说法 1.重新建一个模拟器,名字变一下 2.找到模拟器对应的配置文件,路径不管, ...
- quartz源码分析之深刻理解job,sheduler,calendar,trigger及listener之间的关系
org.quartz包 包org.quartz是Quartz的主包,包含了客户端接口. 其中接口有: Calendar接口: 定义了一个关联Trigger可能(或者不可能)触发的时间空间.它没有定义触 ...
- 关于Bufferedreader的功能扩写
package cn.hncu.pattern.decorator.v1; import java.io.FileReader;import java.io.IOException; public c ...
- ASP.net导出EXCEL乱码?试试这个
网上的方法有说加meta的,是有用,不过,不够直接, 甭管你asp文件是utf-8还是gb2312,加入下面两句就搞掂: response.Charset="GB2312" ses ...
- jedis访问redis学习笔记
最近在学习redis,在网上查了些文章,利用他人已有的知识,总结写下了这篇文章,大部分内容还是引用别人的文章内容.经过测试发现spring-data-redis现在有的版本只能支持reids 2.6和 ...
- delta simulation time[(delta cycle), (delta delay)]
"Delta cycles are an HDL concept used to order events that occur in zero physical time."si ...
- 程序员带你学习安卓开发系列-Android文件存储
这是程序员带你学习安卓开发系列教程.本文章致力于面向对象程序员可以快速学习开发安卓技术. 上篇文章:.Net程序员快速学习安卓开发-布局和点击事件的写法 主要讲解了布局和点击事件的写法. 上篇文章补充 ...