1、Socket(也称套接字)介绍

socket这个东东干的事情,就是帮你把tcp/ip协议层的各种数据封装啦、数据发送、接收等通过代码已经给你封装好了

,你只需要调用几行代码,就可以给别的机器发消息了。

参考https://www.cnblogs.com/weizhixiang/p/6298523.html

2、套接字

所谓socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。应用程 
序通常通过"套接字"向网络发出请求或者应答网络请求。

套接字可以根据通信性质分类,这种性质对于用户是可见的。应用程序一般仅在同一类的 
套接字间进行通信。不过只要底层的通信协议允许,不同类型的套接字间也照样可以通信。套 
接字有两种不同的类型:流套接字和数据报套接字。

3、套接字的工作原理

要通过互联网进行通信,你至少需要一对套接字,其中一个运行于客户机端,我们称之为 
ClientSocket,另一个运行于服务器端,我们称之为ServerSocket。 
    根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个 
步骤:服务器监听,客户端请求,连接确认。

所谓服务器监听,是服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的 
状态,实时监控网络状态。 
    所谓客户端请求,是指由客户端的套接字提出连接请求,要连接的目标是服务器端的套接 
字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的 
地址和端口号,然后就向服务器端套接字提出连接请求。 
    所谓连接确认,是指当服务器端套接字监听到或者说接收到客户端套接字的连接请求,它 
就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦 
客户端确认了此描述,连接就建立好了。而服务器端套接字继续处于监听状态,继续接收其他 
客户端套接字的连接请求。

4、网络编程的解释

网络编程的目的就是指直接或间接地通过网络协议与其他计算机进行通讯。网络编程中 
有两个主要的问题,一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后 
如何可靠高效的进行数据传输。在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的 
路由,由IP地址可以唯一地确定Internet上的一台主机。而TCP层则提供面向应用的可靠的 
或非可靠的数据传输机制,这是网络编程的主要对象,一般不需要关心IP层是如何处理数据 
的。

目前较为流行的网络编程模型是客户机/服务器(C/S)结构。即通信双方一方作为服务 
器等待客户提出请求并予以响应。客户则在需要服务时向服务器提出申请。服务器一般作为 
守护进程始终运行,监听网络端口,一旦有客户请求,就会启动一个服务进程来响应该客 
户,同时自己继续监听服务端口,使后来的客户也能及时得到服务。

在Internet上IP地址和主机名是一一对应的,通过域名解析可以由主机名得到机器的IP, 
由于机器名更接近自然语言,容易记忆,所以使用比IP地址广泛,但是对机器而言只有IP地 
址才是有效的标识符。

通常一台主机上总是有很多个进程需要网络资源进行网络通讯。网络通讯的对象准确的讲 
不是主机,而应该是主机中运行的进程。这时候光有主机名或IP地址来标识这么多个进程显然 
是不够的。端口号就是为了在一台主机上提供更多的网络资源而采取得一种手段,也是TCP层 
提供的一种机制。只有通过主机名或IP地址和端口号的组合才能唯一的确定网络通讯中的对象: 
进程。

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。

在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部。

5、编写Socket套接字的流程

1、服务器端程序的编写步骤:

(1)创建调用socket()函数创建一个用于通信的套接字。#phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

(2)s.bind() 绑定(主机,端口号)到套接字。 #phone.bind(('127.0.0.1',8080))

(3)s.listen() 开始TCP监听 。#phone.listen(5)# 5 代表最多挂机数

(4)s.accept() 被动接受TCP客户的连接,(阻塞式)等待连接的到来。#  conn,client_addr = phone.accept()

(5)处理客户端的连接请求。 # 1、s.recv() 接收数据 /data = conn.recv(1024) # 2、反馈给客户端:s.send() 发送数据

(6)关闭套接字/  s.send() 发送数据

2、客户端程序的编写步骤:

(1)调用socket()函数创建一个用于通信的套接字。# phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

(2)s.connect() 主动初始化TCP服务器连接 # phone.connect(('127.0.0.1',8080))

(3)调用读写函数发送或者接收数据。# s.send() 发送数据(send在待发送数据量大于己端缓存区剩余空间时,数据丢失,不会发完,可后面通过实例解释)

例如:phone.send('hello'.encode('utf-8'))

(4)接受服务端的反馈信息: s.recv() 接收数据 # 例如:
data = phone.recv(1024)
(5)关闭sokect

参考:https://www.cnblogs.com/lixiaoliuer/p/6543968.html
② server.bind(address)

  server.bind(address) 将套接字绑定到地址。address地址的格式取决于地址族。在AF_INET下,以元组(host,port)的形式表示地址

③ server.listen(backlog)

  开始监听传入连接。backlog指定在拒绝连接之前,可以挂起的最大连接数量。backlog等于5,表示内核已经接到了连接请求,但服务器还没有调用accept进行处理的连接个数最大为5,这个值不能无限大,因为要在内核中维护连接队列

④ server.setblocking(bool)

  是否阻塞(默认True),如果设置False,那么accept和recv时一旦无数据,则报错

⑤ conn,addr = server.accept() 

  接受连接并返回(conn,address),其中conn是新的套接字对象,可以用来接收和发送数据。address是连接客户端的地址。接收TCP 客户的连接(阻塞式)等待连接的到来

⑥ client.connect(address)

  连接到address处的套接字。一般,address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。

⑦ client.connect_ex(address)

  同上,只不过会有返回值,连接成功时返回 0 ,连接失败时候返回编码,例如:10061

⑧ client.close()

  关闭套接字

⑨ client.recv(bufsize[,flag])

  接受套接字的数据。数据以字符串形式返回,bufsize指定最多可以接收的数量。flag提供有关消息的其他信息,通常可以忽略

⑩ client.recvfrom(bufsize[.flag])

  与recv()类似,但返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址

⑪ server.send(string[,flag])

  将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。即:可能未将指定内容全部发送

⑫ server.sendall(string[,flag])  

  将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常;

      内部通过递归调用send,将所有内容发送出去

⑬ server.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()

  套接字的文件描述符

6、代码实例

6.1、简单的套接字通信

服务端和客户端在一个IDE下

服务端:

import socket

# 1 买手机
# phone 为套接字对象
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#(sock_stream 流)
# 2 绑定手机卡,127.0.0.1是回送地址,指本地机,一般用来测试使用。客户端、服务端在一台主机上
phone.bind(('127.0.0.1',8081))# 端口 0-65535:0-1024给操作系统使用 # 3 开机
phone.listen(5)# 5 代表最多挂机数 # 4 等电话连接 # 在同一个IDE上执行客户端、服务端,,先执行服务端后,在执行客户端
# 直接执行客户端会发生错误
print('------starting-------')
conn,client_addr = phone.accept() # accept()对于 connect()做的3次握手
# print('==========>')
# print(res) # 5 收、发消息
data = conn.recv(1024) # 1024个字节 代表接受数据最大数,,单位bytes字节
print('客户端数据',data) conn.send(data.upper()) # 服务端回数据给客户端
# 6 挂电话
conn.close() # 7 关机
phone.close()

客户端:

import socket

# 1 买手机
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#(sock_stream 流) # 2 拨号,127.0.0.1是回送地址,指本地机,一般用来测试使用。客户端、服务端在一台主机上
phone.connect(('127.0.0.1',8081))# 端口 0-65535:0-1024给操作系统使用 # 3 发、收 消息
phone.send('hello'.encode('utf-8'))
data = phone.recv(1024)
print(data)
# 4 关闭
phone.close()

服务端先执行,一直开着,然后再执行客户端

6.2、加上链接循环

6.3、简单的远程执行命令程序开发

#-----------windows-----------------
#dir:查看某一个文件夹下的子文件名与子文件夹名
#ipconfig:查看本地网卡的ip信息
#tasklist:查看运行的进程 #----------linux---------------:
#ls
#ifconfig
#ps aux #执行系统命令,并且拿到命令的结果
# import os
# res=os.system('xxxxlxxxs /')
# print('命令的结果是:',res) import subprocess
obj=subprocess.Popen('xxxxxxls /',shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE) print(obj)
print('stdout 1--->: ',obj.stdout.read().decode('utf-8'))
# print('stdout 2--->: ',obj.stdout.read().decode('utf-8'))
#print('stderr 1--->: ',obj.stderr.read().decode('utf-8'))

服务端:

import socket
import subprocess phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind(('127.0.0.1',9901)) #0-65535:0-1024给操作系统使用
phone.listen(5) print('starting...')
while True: # 链接循环
conn,client_addr=phone.accept()
print(client_addr) while True: #通信循环
try:
#1、收命令
cmd=conn.recv(1024)
if not cmd:break #适用于linux操作系统 #2、执行命令,拿到结果
obj = subprocess.Popen(cmd.decode('utf-8'), shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE) stdout=obj.stdout.read()
stderr=obj.stderr.read() #3、把命令的结果返回给客户端
print(len(stdout)+len(stderr))
conn.send(stdout+stderr) #+是一个可以优化的点 except ConnectionResetError: #适用于windows操作系统
break
conn.close() phone.close()

客户端:

import socket

phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

phone.connect(('127.0.0.1',9901))

while True:
#1、发命令
cmd=input('>>: ').strip() #ls /etc
if not cmd:continue
phone.send(cmd.encode('utf-8')) #2、拿命令的结果,并打印
data=phone.recv(1024)
print(data.decode('gbk'))# window用gbk phone.close()

 



19 网络编程--Socket 套接字方法的更多相关文章

  1. 19、网络编程 (Socket套接字编程)

    网络模型 *A:网络模型 TCP/IP协议中的四层分别是应用层.传输层.网络层和链路层,每层分别负责不同的通信功能,接下来针对这四层进行详细地讲解. 链路层:链路层是用于定义物理传输通道,通常是对某些 ...

  2. 网络编程--Socket(套接字)

    网络编程 网络编程的目的就是指直接或间接地通过网络协议与其他计算机进行通讯.网络编程中 有两个主要的问题,一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后 如何可靠高效的进行数据传输.在 ...

  3. 8.7 day28 网络编程 socket套接字 半连接池 通信循环 粘包问题 struct模块

    前置知识:不同计算机程序之间的数据传输 应用程序中的数据都是从程序所在计算机内存中读取的. 内存中的数据是从硬盘读取或者网络传输过来的 不同计算机程序数据传输需要经过七层协议物理连接介质才能到达目标程 ...

  4. python网络编程-socket套接字通信循环-粘包问题-struct模块-02

    前置知识 不同计算机程序之间数据的传输 应用程序中的数据都是从程序所在计算机内存中读取的. 内存中的数据是从硬盘读取或者网络传输过来的 不同计算机程序数据传输需要经过七层协议物理连接介质才能到达目标程 ...

  5. TCP/IP网络编程之网络编程和套接字

    网络编程和套接字 网络编程又称为套接字编程,就是编写一段程序,使得两台连网的计算机彼此之间可以交换数据.那么,这两台计算机用什么传输数据呢?首先,需要物理连接,将一台台独立的计算机通过物理线路连接在一 ...

  6. Linux网络编程——原始套接字实例:MAC 头部报文分析

    通过<Linux网络编程——原始套接字编程>得知,我们可以通过原始套接字以及 recvfrom( ) 可以获取链路层的数据包,那我们接收的链路层数据包到底长什么样的呢? 链路层封包格式 M ...

  7. 【TCP/IP网络编程】:01理解网络编程和套接字

    1.网络编程和套接字 网络编程与C语言中的printf函数和scanf函数以及文件的输入输出类似,本质上也是一种基于I/O的编程方法.之所以这么说,是因为网络编程大多是基于套接字(socket,网络数 ...

  8. UNIX网络编程——原始套接字(dos攻击)

    原始套接字(SOCK_RAW).应用原始套接字,我们可以编写出由TCP和UDP套接字不能够实现的功能. 注意原始套接字只能够由有 root权限的人创建. 可以参考前面的博客<<UNIX网络 ...

  9. UNIX网络编程——原始套接字的魔力【续】

    如何从链路层直接发送数据帧 上一篇里面提到的是从链路层"收发"数据,该篇是从链路层发送数据帧. 上一节我们主要研究了如何从链路层直接接收数据帧,可以通过bind函数来将原始套接字绑 ...

随机推荐

  1. ASP.NET MVC Area 的使用

    MVC提供Area机制,在同一个项目之内就能够切割出不同的ASP.NET MVC网站. 插入:首先在相同的位置,比如说同一个文件夹(如:Controllers)是不能创建俩个相同名称的文件(如:Hom ...

  2. win7上搭建Android环境及调试

    工欲善其事必先利其器,好记性不如烂笔头.要学习一门新的语言,首先必须得先搭环境,否则没法实践.如果之前按照网上的提示,搭建过环境,而且环境比较复杂的话,我相信隔很长一段时间后,就会忘记,到真正用的时候 ...

  3. FastAdmin 开发第三天:认识目录

    以下为标准 FastAdmin 安装后的目录 我们在运行命令时都是在这个目录. 我们所有的命令都在这个目录下面运行. 比如:安装前端组件,bower install 安装php 组件 composer ...

  4. golang panic的捕获

    panic发生时, 会导致进程挂掉.为了处理panic, 可以使用recover捕获,然后处理. 下面以下标引用越界问题为例进行说明. 正常情况下,代码中如果出现下标越界,会直接触发panic, 导致 ...

  5. openwrt设置默认登陆密码

    1.修改dropbear配置文件 找到package/network/services/dropbear/files/dropbear.config 修改如下: config dropbear opt ...

  6. java 装饰设计模式模式

    对已有功能进行增强 示例 已有的类    调用 增强后的类 调用  思考? 为什么要这么做呢? SuperPerson 继承 Person 可以达到同样的效果. 继承的写法,其中MyBuffer... ...

  7. bzoj2035: [2009国家集训队]数据读取问题

    Description Input Output 可以转为边权为1的最短路:将不修改并读取x个数看作有向边,原先树上的边仍保留且视为双向边(但从根出发的边为单向)表示上次读取的修改 第一种边是点到bf ...

  8. java web程序 jdbc连接数据库错误排查方法

    学习jsp.我遇到了麻烦,我总是看不懂500错误,因为每次都显示整个页面的错误,都是英文 我看不懂,后来,把他弄烦了,我也烦了,比起学习java.那个异常可以很简单的就知道.现在解决 了第一个问题,5 ...

  9. [UE4]添加射击的准心

    其实就是创建一个UI Widget,在UI Widget中添加一个准心图片(png)格式,准心图片设置为屏幕居中对齐,然后在自定义的GameMode中把这个UI Widget添加到视图中.

  10. 第10课 C++异常简介

    1. try-catch语句 (1)try语句处理正常代码逻辑 (2)catch语句处理异常情况 (3)try语句中的异常由对应的catch语句处理 (4)C++通过throw语句抛出异常信息 2. ...