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 ...
随机推荐
- Eclipse非常有用的快捷键
Eclipse有强大的编辑功能, 工欲善其事,必先利其器, 掌握Eclipse快捷键,可以大大提高工作效率. 小坦克我花了一整天时间, 精选了一些常用的快捷键操作,并且精心录制了动画, 让你一看就会. ...
- 把谷歌等webkit内核浏览器变为输入文本编辑器的方法
只需要在地址栏输入 data:text/html, <html contenteditable> 回车后即可看到效果
- xml增强学习笔记
2 Dom4j修改xml文档 2.1 写出内容到xml文档 XMLWriter writer = new XMLWriter(OutputStream, OutputForamt) wirter.wr ...
- Sublime_text3怎么发现PHP语法错误?
昨晚因为php的某个变量代码写错了,sublime又没有提示语法错误.弄了许久,一段段的调试,最后才知道是取到的变量是空的 sublime可以提示php语法错误 在sublime写完了php代码后,如 ...
- 在storyboard中的静态UITableView中拖入 UISearchBar and Search Display Controller出现的奇怪问题
近期学习过程中想模拟一下新浪微博"发现"界面. 我在storyboard中拖入一个UITableViewController,设置这个UITableViewCo ...
- [CSS] DOM Hierarchy Pseudo Classes :first-child :last-child :nth-child (demystified)
DOM hierarchy pseudo-classes allow you to style specific elements based on where they fall in the hi ...
- Ⅶ.AngularJS的点点滴滴-- 事件
事件(和js一样有冒泡和捕获) <html> <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2 ...
- Linux下安装Python pip
在Python环境下,pip提供类似yum一样的下载方式,比easy_install方便的多. 1.下载get-pip.py wget https://bootstrap.pypa.io/get-pi ...
- datebox清除按钮,datebox加上清除按钮,easyui datebox加上清除按钮
datebox加上清除按钮,easyui datebox加上清除按钮 >>>>>>>>>>>>>>>>& ...
- javascript的面向对象编程
面象对象编程技术的核心理念:封装.继承.多态:在一些主流的高级编程语言中,比如:C#,VB.NET,JAVA,PHP等都是很容易实现的,而如果要在javascript中实现面象对象编程,可就不那么直接 ...