socket+网路编程
1.网络编程:
通过某种计算机语言来实现不同设备间的资源共享和信息传递。计算机网络的创造可能比计算机本身意义更重大!!!(否则,你只能玩单机版游戏
OSI模型
OSI模型定义了不同计算机互联的标准,是设计和描述计算机网络通信的基本框架。OSI模型把网络通信的工作分为7层,分别是物理层、数据链路层、 网络层、传输层、会话层、表示层和应用层。
网络通信的三要素:
A:IP地址 (1) 用来标识网络上一台独立的主机
(2) IP地址 = 网络地址 + 主机地址(网络号:用于识别主机所在的网络/网段。主机号:用于识别该网络中的主机)
(3) 特殊的IP地址:127.0.0.1(本地回环地址、保留地址,点分十进制)可用于简单的测试网卡是否故障。表示本机。
B:端口号: (1) 用于标识进程的逻辑地址。不同的进程都有不同的端口标识。
(2) 端口:要将数据发送到对方指定的应用程序上,为了标识这些应用程序,所以给这些网络应用程序都用数字进行标识。为了方便称呼这些数字,则将这些数字称为端口。(此端口是一个逻辑端口)
C: 传输协议:通讯的规则。例如:TCP、UDP协议(好比两个人得用同一种语言进行交流)
2. socket 编程
要想理解socket,就要先来理解TCP,UDP协议
TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,定义了主机如何连入因特网及数据如何再它们之间传输的标准,
从字面意思来看TCP/IP是TCP和IP协议的合称,但实际上TCP/IP协议是指因特网整个TCP/IP协议族。不同于ISO模型的七个分层,TCP/IP协议参考模型把所有的TCP/IP系列协议归类到四个抽象层中
应用层:TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 等等
传输层:TCP,UDP
网络层:IP,ICMP,OSPF,EIGRP,IGMP
数据链路层:SLIP,CSLIP,PPP,MTU
每一抽象层建立在低一层提供的服务上,并且为高一层提供服务,看起来大概是这样子的
我们可以利用ip地址+协议+端口号唯一标示网络中的一个进程。能够唯一标示网络中的进程后,它们就可以利用socket进行通信了,我们经常把socket翻译为套接字,socket是在应用层和传输层(TCP/IP协议族通信)之间的一个抽象层,是一组接口,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信。
应用程序两端通过“套接字”向网络发出请求或者应答网络请求。可以把socket理解为通信的把手(hand)
socket起源于UNIX,在Unix一切皆文件哲学的思想下,socket是一种"打开—读/写—关闭"模式的实现,服务器和客户端各自维护一个"文件",在建立连接打开后,可以向自己文件写入内容供对方读取或者读取对方内容,通讯结束时关闭文件。socket的英文原义是“插槽”或“插座”,就像我们家里座机一样,如果没有网线的那个插口,电话是无法通信的。Socket是实现TCP,UDP协议的接口,便于使用TCP,UDP。
通信流程

流程:
# 流程描述:
#
# 1 服务器根据地址类型(ipv4,ipv6)、socket类型、协议创建socket
#
# 2 服务器为socket绑定ip地址和端口号
#
# 3 服务器socket监听端口号请求,随时准备接收客户端发来的连接,这时候服务器的socket并没有被打开
#
# 4 客户端创建socket
#
# 5 客户端打开socket,根据服务器ip地址和端口号试图连接服务器socket
#
# 6 服务器socket接收到客户端socket请求,被动打开,开始接收客户端请求,直到客户端返回连接信息。这时候socket进入阻塞状态,所谓阻塞即accept()方法一直等到客户端返回连接信息后才返回,开始接收下一个客户端连接请求
#
# 7 客户端连接成功,向服务器发送连接状态信息
#
# 8 服务器accept方法返回,连接成功
#
# 9 客户端向socket写入信息(或服务端向socket写入信息)
#
# 10 服务器读取信息(客户端读取信息)
#
# 11 客户端关闭
#
# 12 服务器端关闭
来一个简单的例子来看一下,服务端和客户端之间相互通信
2.1 serve端
import socket
sk = socket.socket()
print(sk) address = ("127.0.0.1",9000)
sk.bind(address)
sk.listen(3) #表示最多只能等待三人
print("waiting...............")
conn,addr = sk.accept()
#inp = input(">>>")
#conn.send(byte(inp,"utf8"))
data = conn.recv(1024)
print(data)
conn.close()
sk.close()
client端
import socket
sk = socket.socket()
print(sk) address = ("127.0.0.1",9000)
sk.connect(address)
data = sk.send(bytes("haha","utf8")) #阻塞 #print(str(data,"utf8"))
sk.close()
print(sk)
这样就简单实现了服务端和客户端之间的一次通信,但是有时候我们并不是只进行一次通信,我们也许会有好几次,也可以停止聊天和另外一个用户聊,所以呢这时候就可以用到循环了,可以再看下面一个例子就可以当做是屌丝追女神
服务端:
import socket
sk = socket.socket()
print(sk)
address = ("127.0.0.1",9000)
sk.bind(address) #为socket绑定IP和端口号
sk.listen(3) #监听设置端口等待客户端的请求
print("waiting...............")
while 1:
conn,addr = sk.accept() #accept阻塞,直到有客户端来连接
#print(coon)
#print(sk.accept())
print(addr)
while 1:
data = conn.recv(1024)
# try: #如果在客户端直接暂停 进行异常处理
# data = conn.recv(1024)
# except Exception:
# break
print("......",str(data,"utf8"))
if not data:break
inp = input(">>>")
conn.send(bytes(inp,"utf8"))
sk.close()
客户端:
import socket
sk = socket.socket()
print(sk) address = ("127.0.0.1",9000)
sk.connect(address) while True:
inp = input(">>>")
if inp == "exit":
break
sk.send(bytes(inp,"utf8"))
data = sk.recv(1024)
print(str(data,"utf8"))
sk.close()
注意:
1 一收一发
2 client_data=conn.recv(1024)
if 那边send一个空数据 这边recv为空,则recv继续阻塞,等待其他的数据。所以聊天的时候好好聊,别发空数据。
3. 远程执行命令
我们希望不仅能在服务端和客户端之间进行交流,有时候我们也希望能在一端执行命令(dir,ifconfig,cd等等),另外一端显示结果
那么我们直接来看例子,
cmd_serve端
import socket,subprocess#词模块下只有一个参数
sk = socket.socket()
print(sk)
address = ("127.0.0.1",9000)
sk.bind(address)
sk.listen(3)
print("waiting...............")
while 1:
conn,addr = sk.accept()
#print(coon)
#print(sk.accept())
print(addr)
while 1:
try: #如果在客户端直接暂停处理异常
data = conn.recv(1024)
except Exception:
break
if not data:break
print("......", str(data, "utf8"))
obj = subprocess.Popen(data.decode("utf8"),shell = True,stdout = subprocess.PIPE)
cmd_result = obj.stdout.read()
result_len = bytes(str(len(cmd_result)),"utf8")
print(">>>>>>>>>>",result_len)
conn.sendall(result_len) #粘包现象
#解决粘包conn.recv(1024)
conn.sendall(cmd_result)
sk.close()
注意:
1 sendall并不会把数据直接全部发送到客户端,而是将所有的数据都放到缓冲区(理解成一艘艘货船),缓冲区一次最多发送1024字节的数据到客户端
2 比如第一次的结果有1124字节,那么放在两艘船上,一艘满的,一艘只有100字节;那么这一次只会讲满的1024字节结果发送到客户端,程序并不会阻塞在这里,会继续向下执行,recv新的命令执行,比如第二次的结果有200字节数据,那么这两百字节的结果也会放到刚才未满的货船上总共300字节一起发送过去。
cmd_client端
import socket
sk = socket.socket()
print(sk) address = ("127.0.0.1",9000)
sk.connect(address) while True:
inp = input(">>>")
if inp == "exit":
break
sk.send(bytes(inp,"utf8"))
result_len = int(str(sk.recv(1024),"utf8"))
sk.sendall('') #解决粘包问题
print(result_len)
data = bytes()
while len(data) != result_len:
recv = sk.recv(1024)
data += recv
print(str(data,"gbk"))
sk.close()
这样就可以实现在客户端输入命令查看信息,在服务端就可以按到命令的端口号以及IP地址,也同事处理了粘包的问题
4. 编码转换指示
4.1 在PY3中:只有str和bytes2种编码
str:unicode(万国码)
bytes:(十六进制)
s='hello袁浩'
2 print(type(s)) #<class 'str'>
4.2 编码规则:
# 规则
# str>>>>>>>>>>>>>>bytes:编码 b=bytes(s,'utf8')
print(b)#b'hello\xe8\xa2\x81\xe6\xb5\xa9' #utf8规则下的bytes类型 b2=s.encode('utf8')
print(b2)#b'hello\xe8\xa2\x81\xe6\xb5\xa9' #utf8规则下的bytes类型 b3=s.encode('gbk')
print('gbk编码下的bytes数据:',b2)# b'hello\xd4\xac\xba\xc6' # bytes>>>>>str:解码 # s=str(b2,'gbk')
# print(s)#hello琚佹旦 乱码了 # # 解码方法1:
# s=str(b2,'utf8')
# print(s)#hello袁浩 #str数据类型
#
# # 解码方法2:
# s2=b2.decode('utf8')
#
# print(s2)#hello袁浩 # s3=b3.decode('gbk')
# print(s3)#hello袁浩
5.文件上传:
import socket,os
ip_port=("127.0.0.1",8898)
sk=socket.socket()
sk.bind(ip_port)
sk.listen(5)
BASE_DIR=os.path.dirname(os.path.abspath(__file__)) while True:
print("waiting connect")
conn,addr=sk.accept()
flag = True
while flag: client_bytes=conn.recv(1024)
client_str=str(client_bytes,"utf8")
func,file_byte_size,filename=client_str.split("|",2) path=os.path.join(BASE_DIR,'yuan',filename)
has_received=0
file_byte_size=int(file_byte_size) f=open(path,"wb")
while has_received<file_byte_size:
data=conn.recv(1024)
f.write(data)
has_received+=len(data)
print("ending")
f.close() #----------------------------------------------client
#----------------------------------------------
import socket
import re,os,sys
ip_port=("127.0.0.1",8898)
sk=socket.socket()
sk.connect(ip_port)
BASE_DIR=os.path.dirname(os.path.abspath(__file__))
print("客户端启动....") while True:
inp=input("please input:") if inp.startswith("post"):
method,local_path=inp.split("|",1)
local_path=os.path.join(BASE_DIR,local_path)
file_byte_size=os.stat(local_path).st_size
file_name=os.path.basename(local_path)
post_info="post|%s|%s"%(file_byte_size,file_name)
sk.sendall(bytes(post_info,"utf8"))
has_sent=0
file_obj=open(local_path,"rb")
while has_sent<file_byte_size:
data=file_obj.read(1024)
sk.sendall(data)
has_sent+=len(data)
file_obj.close()
print("上传成功")
socket+网路编程的更多相关文章
- windows下的socket网络编程
windows下的socket网络编程 windows下的socket网络编程 clinet.c 客户端 server.c 服务器端 UDP通信的实现 代码如下 已经很久没有在windows下编程了, ...
- windows下的socket网络编程(入门级)
windows下的socket网络编程 clinet.c 客户端 server.c 服务器端 UDP通信的实现 代码如下 已经很久没有在windows下编程了,这次因为需要做一个跨平台的网络程序,就先 ...
- Java复习9网路编程
Java 复习9网路编程 20131008 前言: Java语言在网络通信上面的开发要远远领先于其他编程语言,这是Java开发中最重要的应用,可以基于协议的编程,如Socket,URLConnecti ...
- Java Web 基础(一) 基于TCP的Socket网络编程
一.Socket简单介绍 Socket通信作为Java网络通讯的基础内容,集中了异常.I/O流模式等众多知识点.学习Socket通信,既能够了解真正的网络通讯原理,也能够增强对I/O流模式的理解. 1 ...
- Linux Socket 网络编程
Linux下的网络编程指的是socket套接字编程,入门比较简单.在学校里学过一些皮毛,平时就是自学玩,没有见识过真正的socket编程大程序,比较遗憾.总感觉每次看的时候都有收获,但是每次看完了之后 ...
- Python Socket 网络编程
Socket 是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于 Socket 来完成通信的,例如我们每天浏览网页.QQ ...
- Python全栈【Socket网络编程】
Python全栈[socket网络编程] 本章内容: Socket 基于TCP的套接字 基于UDP的套接字 TCP粘包 SocketServer 模块(ThreadingTCPServer源码剖析) ...
- python之Socket网络编程
什么是网络? 网络是由节点和连线构成,表示诸多对象及其相互联系.在数学上,网络是一种图,一般认为专指加权图.网络除了数学定义外,还有具体的物理含义,即网络是从某种相同类型的实际问题中抽象出来的模型.在 ...
- Python之路【第七篇】python基础 之socket网络编程
本篇文章大部分借鉴 http://www.cnblogs.com/nulige/p/6235531.html python socket 网络编程 一.服务端和客户端 BS架构 (腾讯通软件:ser ...
随机推荐
- 原生Javascript插件开发实践
前言 之前公司设计的网站比较混乱,很多地方不统一,其中一个就是弹出层,导致这个原因是因为,公司的UI换了好几个人,而他们每个人做出来的都不太一样.最近公司开始整顿这个问题,对于统一的这种东西当然是做成 ...
- asp.net redis 实战
当开始用 var result=new RedisClient("127.0.0.1",6379,1"1111"); 这个helper ,后面有并发之后 ...
- Yii 安装二维码扩展Qrcode
比如要添加 https://github.com/2amigos/yii2-qrcode-helper 生成二维码的 这个扩展第一种方法 : 1.打开根目录的composer.json, 在re ...
- C#面向对象基础:virtual方法,abstract方法,区别
virtual 关键字用于修饰方法.属性.索引器或事件声明,并使它们可以在派生类中被重写.默认情况下,类中的方法是非虚的,非虚的方法不能在子类中被覆盖(override),但是可以隐藏(new),但这 ...
- 在Mybatis-spring中由于默认Autowired导致不能配置多个数据源的问题分析及解决
在使用Mybatis中,通常使用接口来表示一个Sql Mapper的接口以及相对应的xml实现,而在spring的配置文件中,通常会使用MapperScannerConfigurer来达到批量扫描以及 ...
- (转)Zend Studio 10.6.1破解注册图文详解
原文来自:http://www.softown.cn/soft/zend-studio/windows/10.6.1#downloads 下面我们以Zend Studio 10.6.1正式版为例来介绍 ...
- 【AOS应用基础平台】完好了AOS标签库,和标准标签库完美兼容了
[金码坊AOS开发平台]今天①完好了AOS标签库,和标准标签库完美兼容了.②新开发了依据子页面动态生成主页面的二级导航菜单功能.#AOS开发平台#
- CFileDialog的使用方法简单介绍
CFileDialog文件选择对话框的使用:首先构造一个对象并提供对应的參数,构造函数原型例如以下: CFileDialog::CFileDialog( BOOL bOpenFileDialog, L ...
- nodejs保存文件的问题
从前端到那里jar包失败: 保存到本地管理机jar包md5sum上传正确的值md5sum值不相等.并上传 处理 没有错误,说明保存过程中的错误: 前面是base64然后转码后jar包内容放进reque ...
- C#生成XML的三种途径
C#生成XML的三种途径 为了全面,这里都将XML保存到文件中,有三种生成XML的方式: 1.我认为是最原始,最基本的一种:利用XmlDocument向一个XML文件里写节点,然后再利用XmlDocu ...