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 ...
随机推荐
- Quartz定时任务学习(九)Quartz监听器
Quartz 提供了三种类型的监听器:监听 Job 的,监听 Trigger 的,和监听 Scheduler 自已的. 本章解释如何应用每一种类型来更好的管理你的 Quartz 应用,并获悉到什么事件 ...
- Can't connect to MySQL server on localhost (10061)解决方法
出现这种错误的原因是由于MySQL的服务被关闭的原因,重新启动一下服务就可以了,启动服务的操作如下: 右键[计算机]-[管理]
- java基础入门-arraylist存储开销
今天我们来看一下arraylist的存储开销,由于在项目其中,我尝试了一个很大的arraylist.然后内存爆了 所以我看了下源代码.原来arraylist的存储开销是比較大的,先上代码 import ...
- NuGet的使用心得
前言 上星期发布了NuGet的使用和服务搭建后,同时NuGet在部门里也使用了起来.经过这些天的使用,总结了些小技巧和注意点,希望和大家分享下. 问题提出 使用了NuGet的朋友们估计都知道,在签入代 ...
- 统计功能和子对象的大小信息查询Bug
I hava below two statement sql: 0. not in subquery select a.schemaname, pg_size_pretty(pg_total_rela ...
- lua wireshark 数据报解析
http://www.360doc.com/content/13/1226/15/15257968_340284574.shtml http://www.360doc.com/userhome.asp ...
- hadoop错误FATAL org.apache.hadoop.hdfs.server.namenode.NameNode Exception in namenode join java.io.IOException There appears to be a gap in the edit log
错误: FATAL org.apache.hadoop.hdfs.server.namenode.NameNode Exception in namenode join java.io.IOExcep ...
- dell笔记本通过uefi+gpt模式安装win10系统
安装前,需要确认dell笔记本是否支持uefi 1.使用UltraISO制作硬盘镜像后,过程如下 1) 选择"文件"->"打开",如下 2) 在打开的对话 ...
- C#泛型的性能优势
我写东西一向追求短小精悍,就不放代码去验证的,只说结论,并会与Java泛型做对比.有不对之处还望指出. 泛型作为一个在C#2.0中就引入的特性,也是C#的重要特性之一,我经常看到有人讨论泛型带来的便捷 ...
- java注释 命名 数据类型 基本类型转换 位运算符 逻辑运算符 三目运算符
一.java注释 1.单行注释 //注释内容 2.多行注释 /*注释内容*/ 3.文档注释(可用javadoc工具生成api文档,不过我还没试过)/**文档注释*/,文档注释可以在使用的时候看见注释 ...