一、客户端/服务器架构

1、C/S结构,即Client/Server(客户端/服务器)结构

2、我们在互联网中处处可见c/s架构比如说浏览器,qq,lol,视频软件。。。

3、我们学习socket就是为了c/s架构的开发


二、scoket与网络协议

首先我们需要实现网络通信必然需要多网络协议有着深刻的了解。而我们做开发如果把每一点都搞清楚太过于耗费精力,所以我们才有了scoket

socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

所以,我们无需深入理解tcp/udp协议,socket已经为我们封装好了,我们只需要遵循socket的规定去编程,写出的程序自然就是遵循tcp/udp标准的


三、套接字

套接字起源于 20 世纪 70 年代加利福尼亚大学伯克利分校版本的 Unix,即人们所说的 BSD Unix。一开始,套接字被设计用在同 一台主机上多个应用程序之间的通讯。套接字有两种(或者称为有两个种族),分别是基于文件型的和基于网络型的。

1、基于文件类型的套接字:AF_UNIX

unix一切皆文件,基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进程运行在同一机器,可以通过访问同一个文件系统间接完成通信

2、基于网络类型的套接字:AF_INET

还有AF_INET6被用于ipv6,还有一些其他的地址家族,AF_INET是使用最广泛的一个,python支持很多种地址家族,但是由于我们只关心网络编程,所以大部分时候我么只使用AF_INET

3、套接字函数的认识

首先我们要知道所有的函数使用都需要导入socket模块

1)socket()模块

import socket
获取tcp/ip套接字
tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 获取udp/ip套接字
udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

2)服务端套接字函数

bind()    绑定(主机,端口号)到套接字
listen() 开始TCP监听
accept() 被动接受TCP客户的连接,(阻塞式)等待连接的到来

3)客户端套接字函数

connect()     主动初始化TCP服务器连接
connect_ex() connect()函数的扩展版本,出错时返回出错码,而不是抛出异常

4)公共用途的套接字函数

recv()            接收TCP数据
send() 发送TCP数据(send在待发送数据量大于己端缓存区剩余空间时,数据丢失,不会发完)
sendall() 发送完整的TCP数据(本质就是循环调用send,sendall在待发送数据量大于己端缓存区剩余空间时,数据不丢失,循环调用send直到发完)
recvfrom() 接收UDP数据
sendto() 发送UDP数据
getpeername() 连接到当前套接字的远端的地址
getsockname() 当前套接字的地址
getsockopt() 返回指定套接字的参数
setsockopt() 设置指定套接字的参数
close() 关闭套接字

5)面向锁的套接字函数

setblocking()     设置套接字的阻塞与非阻塞模式
settimeout() 设置阻塞套接字操作的超时时间
gettimeout() 得到阻塞套接字操作的超时时间

6)面向文件的套接字函数

fileno()          套接字的文件描述符
makefile() 创建一个与该套接字相关的文件

四、基于tcp的套接字代码实现

前面一次性近二十个函数是不是看蒙蔽了 来看看实际应用其实应用很简单

tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端

tcp服务端

ss = socket()      #创建服务器套接字
ss.bind() #把地址绑定到套接字
ss.listen() #监听链接
while True : #服务器无限循环
conn,client_addr=ss.accept() #接受客户端链接
while True : #通讯循环
conn.recv()/cs.send() #对话(接收与发送)
conn.close() #关闭客户端套接字
ss.close() #关闭服务器套接字(可选)

tcp客户端

cs = socket()    # 创建客户套接字
cs.connect() # 尝试连接服务器
while True : # 通讯循环
cs.send()/cs.recv() # 对话(发送/接收)
cs.close() # 关闭客户套接字

1、socket通信流程与打电话流程类似以此为例:

服务端:

import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #买手机
s.bind('127.0.0.1',8080) #手机插卡
s.listen(5) #开机 #print('starting...')
conn,addr=s.accept() #等电话 (链接,客户的的ip和端口组成的元组)
#print(conn,addr) data=conn.recv(1024) #接收
print('client data: <%s>' %data)
conn.send(data.upper()) #发送 conn.close() #挂电话
s.close() #关机

客户端:

import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #买手机
phone.connect(('127.0.0.1',8080)) #绑定手机卡 #发,收消息
phone.send('hello'.encode('utf-8'))
data=phone.recv(1024)
print('server back res:<%s>' %data) phone.close()

2、加上链接循环与通信循环

服务端:

import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #买手机
phone.bind(('127.0.0.1',8081)) #绑定手机卡
phone.listen(5) #开机 最多挂起5个服务 print('starting...')
while True: #链接循环
conn,client_addr=phone.accept() #等电话 (链接,客户的的ip和端口组成的元组)
print('-------->',conn,client_addr) #收,发消息
while True:#通信循环
try:
data=conn.recv(1024)
if not data:break #针对linux
print('client data: <%s>' %data)
conn.send(data.upper())
except Exception:
break
conn.close() #挂电话
phone.close() #关机

客户端(可以有几个客户端一起链接后面的被挂起前一个断开后立马链接):

import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #买手机
phone.connect(('127.0.0.1',8081)) #绑定手机卡 #发,收消息
while True:
msg=input('>>: ').strip()
if not msg:continue
phone.send(msg.encode('utf-8'))
data=phone.recv(1024)
print('server back res:<%s>' %data) phone.close()

3、模拟ssh远程模拟命令

服务端:

import socket
import subprocess
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.bind(('127.0.0.1',8082))
phone.listen(5) print('starting...')
while True:
conn,client_addr=phone.accept()
print('-------->',conn,client_addr) while True:
try:
cmd=conn.recv(1024)
#if not cmd:break #针对linux
#执行cmd命令,拿到cmd的结果,结果应该是bytes类型
#。。。。
res = subprocess.Popen(cmd.decode('utf-8'), shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout=res.stdout.read()
stderr=res.stderr.read() #发送命令的结果
conn.send(stdout+stderr)
except Exception:
break
conn.close() #挂电话
phone.close() #关机

客户端:

import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(('127.0.0.1',8082)) while True:
cmd=input('>>: ').strip()
if not cmd:continue
phone.send(cmd.encode('utf-8'))
cmd_res=phone.recv(1024)
print(cmd_res.decode('gbk'))
phone.close()

五、异常解决(了解)

解决方法:

#加入一条socket配置,重用ip和端口

phone=socket(AF_INET,SOCK_STREAM)
phone.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加
phone.bind(('127.0.0.1',8080))

六、subprocess模块(简单介绍)

允许你去创建一个新的进程让其执行另外的程序,并与它进行通信,获取标准的输入、标准输出、标准错误以及返回码等

Popen类

subprocess模块中定义了一个Popen类,通过它可以来创建进程,并与其进行复杂的交互。查看一下它的构造函数:

__init__(self, args, bufsize=0, executable=None,
stdin=None, stdout=None, stderr=None, preexec_fn=None,
close_fds=False, shell=False, cwd=None, env=None,
universal_newlines=False, startupinfo=None,
creationflags=0)

主要参数说明: 
args:args should be a string, or a sequence of program arguments.也就是说必须是一个字符串或者序列类型(如:字符串、list、元组),用于指定进程的可执行文件及其参数。如果是一个序列类型参数,则序列的第一个元素通常都必须是一个可执行文件的路径。当然也可以使用executeable参数来指定可执行文件的路径。

stdin,stdout,stderr:分别表示程序的标准输入、标准输出、标准错误。有效的值可以是PIPE,存在的文件描述符,存在的文件对象或None,如果为None需从父进程继承过来,stdout可以是PIPE,表示对子进程创建一个管道,stderr可以是STDOUT,表示标准错误数据应该从应用程序中捕获并作为标准输出流stdout的文件句柄。

shell:如果这个参数被设置为True,程序将通过shell来执行。 
env:它描述的是子进程的环境变量。如果为None,子进程的环境变量将从父进程继承而来。

实例化:

res = subprocess.Popen(r'dir', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

初始socket的更多相关文章

  1. python 初始socket

    一.网络基础 1.c\s架构:客户端英文名称:Client(使用服务端的服务),服务端英文名称:Server 软件c\s架构:QQ.微信.优酷.暴风影音.浏览器(IE.火狐,360浏览器等): 软件b ...

  2. 网络 --- 1 c/s (b/s)架构 ip 初始socket

    一.c/s   b/s c/s架构:客户端(client)/服务器(server) 软件cs架构:微信,陌陌,qq等 硬件cs架构:打印机 b/s架构:浏览器(browser)/服务器(server) ...

  3. Pyhont 网络编程【第一篇】初始Socket网络套接字

    一.什么是socket: Socket 别名 “网络套接字”,指网络通信链句柄 其实就是一堆网络信息(ip+端口) 建立起的链接称之为socket,Socket的英文原义是“孔”或“插座”,用来实现不 ...

  4. 初始Socket编程(python)

    通信双方要有一个服务端和一个客户端,所以要分开去写代码. 所以我创建了两个py程序,第一个是服务端:iServer.py 和客户端 iClient.py 服务端: #coding:utf-8from ...

  5. 初始socket模块和巧解粘包问题

    1.什么是socket? 两个进程如果需要进行通讯最基本的一个前提能够唯一的标示一个进程,在本地进程通讯中我们可以使用PID来唯一标示一个进程,但PID只在本地唯一,网络中的两个进程PID冲突几率很大 ...

  6. 初始socket编程

    服务端语法 import socket # 导入套接字模块# 生成一个socket对象进行网络编程操作server = socket.socket(family=socket.AF_INET, typ ...

  7. linux下socket编程-进程间通信

    一.什么是Socket Socket接口是TCP/IP网络通信的API,Socket接口定义了许多函数或例程,可以用它们来开发TCP/IP网络上的应用程序. Socket类型有两种:流式Socket ...

  8. 6.1.1Linux下Socket编程

    什么是Socket Socket接口是TCP/IP网络的API,Socket接口定义了许多函数或例程,程序员可以用它们来开发TCP/IP网络上的应用程序.要学Internet上的TCP/IP网络编程, ...

  9. .Net中的socket编程例子

    vb2010: '发送端代码Public Class Form1    Inherits System.Windows.Forms.FormPrivate Sub Button1_Click(ByVa ...

随机推荐

  1. Add lombok to IntelliJ IDEA

    Lombok study link: https://www.jianshu.com/p/365ea41b3573 Add below dependency code to pom.xml <d ...

  2. oracle 新增字段

    alter table shop_procategory add (category_ORDER_FIELD number(10) default '0' not null);comment on c ...

  3. Learning Python 006 list(列表) 和 tuple(元组)

    Python list(列表) 和 tuple(元组) list 列表 Python内置的一种数据结构.list:一种有序的集合,可以随时添加和删除其中的元素. list的用法 定义list > ...

  4. 6、R语言绘制带errorbar 的柱状图

    转载:http://www.cnblogs.com/xudongliang/p/7283733.html data <- data.frame(mean = c(10, 15), sd = c( ...

  5. Java基础——java中String、StringBuffer、StringBuilder的区别

    (转自:http://www.cnblogs.com/xudong-bupt/p/3961159.html) java中String.StringBuffer.StringBuilder是编程中经常使 ...

  6. 关于mysql查询最近一条记录

    关于mysql查询最近一条记录 最近项目中遇到需要查询记录当前时间最近的一条记录的问题,开始感觉无从下手,后来逐步发现了三种解决方案. 下策——查询出结果后将时间排序后取第一条 select * fr ...

  7. Flash builder发布Air程序时设备配置文件supportedProfiles的配置

    1. 发布的程序:需要访问本地进程,那么只能发布为exe程序才可以.   此时supportedProfiles 配置为 extendedDesktop desktop   desktop保证能发布a ...

  8. 利用StoryBoard编写UITabelViewCell

    举一个炒鸡简单的例子: - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPa ...

  9. lable对picbox透明

    为了登录美观一些,就在窗体上加了个picbox.并且充满了整个窗体. 往上面放了几个lable,把lable属性设置Transparent.本想着lable不会有底色,实际上有个底,很难看. 解决办法 ...

  10. C++基础之类和对象二

    (1)指向类的成员的指针分为指向数据成员的指针和指向成员函数的指针两种.一个类的对象用运算符“.*”来操作指向该类成员的指针,而一个指向类的对象的指针用运算符“->”来操作指向该类成员的指针.( ...