精华内容
下载资源
问答
  • Socket编程

    2021-03-05 11:32:02
    1.1 Socket 是什么 Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口 1.1.1 Socket 在哪里 1.1.2 socket如何交互 服务端: 初始化socket,与端口进行绑定,对端口进行监听,调用accept阻塞,等待...

    1 概述

    1.1 Socket 是什么

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

    1.1.1 Socket 在哪里

    在这里插入图片描述

    1.1.2 socket如何交互

    在这里插入图片描述

    服务端:

    初始化socket,与端口进行绑定,对端口进行监听,调用accept阻塞,等待客户端连接。

    此时,如果有一个客户端初始化socket,然后连接服务器,如果连接成功,这时客户端与服务器端的连接就建立了。

    客户端发送数据请求,服务端接收并处理请求,然后把应答数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。

    1.2 网络中的进程如何通信:socket

    通过三元组标识网络中的进程(ip地址,协议,端口),网络中的进程就可以利用这个标志与其它进程进行通信。

    一切皆socket

    Linux的哲学之一就是:一切皆文件——都可以用打开open,读read/写write,关闭close模式来进行操作。

    我的理解就是Socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭),这些函数我们在后面进行介绍。

    2 使用

    Socket的基本操作

    既然socket是“open—write/read—close”模式的一种实现,那么socket就提供了这些操作对应的函数接口。下面以TCP为例,介绍几个基本的socket接口函数。

    socket 是一种特殊的I/O

    服务端函数:
    bind,listen,accept
    客户端函数:
    connect,connet_ex

    2.1 socket() 函数

    socket(family,type[,protocal])

    socket 函数 相当于一个open 操作。

    普通文件的打开操作返回一个文件描述字,而socket()用于创建一个socket描述符(socket descriptor),它唯一标识一个socket。

    这个描述字与文件描述字一样,后续的操作都有用到它,把它作为参数,通过它来进行一些读写操作。

    socket函数的三个参数分别为:

    family:即协议域,又称为协议族(family)。常用的协议族有,AF_INET、AF_INET6、AF_LOCAL(或称AF_UNIX,Unix域socket)、AF_ROUTE等等。协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址。

    套接字分类:1、基于文件类型的套接字家族;套接字家族的名字:AF_UNIX
    2、基于网络类型的套接字家族;套接字家族的名字:AF_INET

    type:指定socket类型。常用的socket类型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等.

    流式Socket(SOCK_STREAM)流式是一种面向连接的Socket,针对于面向连接的TCP服务应用;

    **数据报式Socket(SOCK_DGRAM)**数据报式Socket是一种无连接的Socket,对应于无连接的UDP服务应用。

    protocol:故名思意,就是指定协议。常用的协议有,IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议

    当我们调用socket创建一个socket时,返回的socket描述字它存在于协议族(address family,AF_XXX)空间中,但没有一个具体的地址。如果想要给它赋值一个地址,就必须调用bind()函数

    不使用bind(),当调用connect()、listen()时系统就会自动随机分配一个端口。

    2.2 bind () 函数

    s.bind(address)

    将套接字绑定到地址, 在AF_INET下,以元组(host,port)的形式表示地址address

    通常服务器在启动的时候都会绑定一个众所周知的地址(如ip地址+端口号),用于提供服务,客户就可以通过它来接连服务器;而客户端就不用指定,有系统自动分配一个端口号和自身的ip地址组合。这就是为什么通常服务器端在listen之前会调用bind(),而客户端就不会调用,而是在connect()时由系统随机生成一个。

    2.3 listen()

    s.listen(backlog)

    开始监听TCP传入连接。

    backlog指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了。

    2.4 accept()

    s.accept()

    接受TCP连接并返回(conn,address),其中conn是新的套接字对象,可以用来接收和发送数据。address是连接客户端的地址。
    同时,也起到了阻塞进程的作用。

    2.5 connect

    s.connect(address)

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

    2.6 接收数据

    s.recv(bufsize[,flag])

    接收TCP套接字的数据。

    数据以字符串形式返回。

    bufsize指定要接收的最大数据量。

    flag提供有关消息的其他信息,通常可以忽略。

    s.recvfrom(bufsize[.flag])

    接受UDP套接字的数据。

    与recv()类似,但返回值是(data,address)。

    其中data是包含接收数据的字符串,address是发送数据的套接字地址。

    2.7 发送

    send(string[,flag])

    发送TCP数据。将string中的数据发送到连接的套接字。

    返回值是要发送的字节数量,该数量可能小于string的字节大小.

    sendall(string[,flag])

    完整发送TCP数据。

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

    s.sendto(string[,flag],address)

    发送UDP数据。将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。

    返回套接字

    s.getpeername()

    返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。

    s.getsockname()

    返回套接字自己的地址。通常是一个元组(ipaddr,port)

    超时

    s.settimeout(timeout)

    设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如connect())

    s.gettimeout()

    返回当前超时期的值,单位是秒,如果没有设置超时期,则返回None。

    s.setblocking(flag)

    如果flag为0,则将套接字设为非阻塞模式,否则将套接字设为阻塞模式(默认值)。非阻塞模式下,如果调用recv()没有发现任何数据,或send()调用无法立即发送数据,那么将引起socket.error异常。

    3 socket编程

    3.1 编程思路

    TCP服务端:

    1 创建套接字,绑定套接字到本地IP与端口

    socket.socket(socket.AF_INET,socket.SOCK_STREAM)

    s.bind()

    2 开始监听连接
    #s.listen()

    3 进入循环,不断接受客户端的连接请求
    #s.accept()

    4 然后接收传来的数据,并发送给对方数据
    #s.recv() , s.sendall()

    5 传输完毕后,关闭套接字
    #s.close()

    TCP客户端:

    1 创建套接字,连接远端地址

       # socket.socket(socket.AF_INET,socket.SOCK_STREAM) ,
       # s.connect()
    

    2 连接后发送数据和接收数据
    # s.sendall()
    # s.recv()

    3 传输完毕后,关闭套接字
    #s.close()
    在这里插入图片描述

    3.2 代码实例

    Socket编程之服务端代码:

    import socket   #socket模块
    import commands   #执行系统命令模块
    HOST='10.0.0.245'
    PORT=50007
    s= socket.socket(socket.AF_INET,socket.SOCK_STREAM)   #定义socket类型,网络通信,TCP
    s.bind((HOST,PORT))   #套接字绑定的IP与端口
    s.listen(1)         #开始TCP监听,监听1个请求
    while 1:
           conn,addr=s.accept()   #接受TCP连接,并返回新的套接字与IP地址
           print'Connected by',addr    #输出客户端的IP地址
           while 1:
                    data=conn.recv(1024)    #把接收的数据实例化
                   cmd_status,cmd_result=commands.getstatusoutput(data)  
                    #commands.getstatusoutput执行系统命令(即shell命令),返回两个结果,第一个是状态,成功则为0,第二个是执行成功或失败的输出信息
                    if len(cmd_result.strip()) ==0:   #如果输出结果长度为0,则告诉客户端完成。此用法针对于创建文件或目录,创建成功不会有输出信息
                            conn.sendall('Done.')
                    else:
                           conn.sendall(cmd_result)   #否则就把结果发给对端(即客户端)
    conn.close()     #关闭连接
    

    Socket编程之客户端代码:

    import socket
    HOST='10.0.0.245'
    PORT=50007
    s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)      #定义socket类型,网络通信,TCP
    s.connect((HOST,PORT))       #要连接的IP与端口
    while 1:
           cmd=raw_input("Please input cmd:")       #与人交互,输入命令
           s.sendall(cmd)      #把命令发送给对端
           data=s.recv(1024)     #把接收的数据定义为变量
            print data         #输出变量
    s.close()   #关闭连接
    

    https://www.cnblogs.com/wumingxiaoyao/p/7047658.html

    if __ name __ ==‘main’ 用法

    if __name__== '__main__':
    

    python脚本的执行方式有两种:
    1、作为脚本直接执行
    2、Import到其它的脚本中被调用(模块重用)执行

    if name==‘main’: 只有在第一种方式下才运行

    init() 与 self对象

    class Person(object):
        def __init__(self, name, lang, website):
            self.name = name
            self.lang = lang
            self.website = website
     
            print('self: ', self)
            print('type of self: ', type(self))
    '''
    未实例化时,运行程序,构造方法没有运行
    '''
     
    p = Person('Tim', 'English', 'www.universal.com')   
     
    '''实例化后运行的结果
    self:  <__main__.Person object at 0x00000000021EAF98>
    type of self:  <class '__main__.Person'>
    
    展开全文
  • Socket 编程原理

    2021-03-30 15:27:51
    目录socket编程基本概念协议TCPUDPDNSICMPHTTPHTTPS编程流程socket函数 socket编程 基本概念 socket编程即计算机网络编程,目的是使两台主机能够进行远程连接,既然要使两者产生联系,那么就要有至少一个信息发送端...

    socket编程

    基本概念

    socket编程即计算机网络编程,目的是使两台主机能够进行远程连接,既然要使两者产生联系,那么就要有至少一个信息发送端和一个信息接收端,因此形成了现在绝大多数 socket 编程都会用到的 C/S 架构(Client[客户端]/Server[服务端]),最典型的应用就是 web服务器/客户端。
    在 Unix/Linux 中执行任何形式的 I/O 操作(比如网络连接)时,都是在读取或写入一个文件描述符,而在 Windows 中则被称为文件句柄,其本质都是一个东西,但是 Windows系统会把 socket 当成一个网络连接,需要调用专门设计的数据传输函数。
    socket (套接字)是一种抽象层,程序通过它来收发数据,就像打开一个句柄将数据写在存储器上一样,使用 socket 能将程序放在网络中,并与同一网络下其他计算机进行通信。
    现在问题又来了,主机内部应用间进行通信,不同应用可用进程号作为唯一标识,那么在网络间通信用什么作为唯一标识呢?其实 TCP/IP 协议簇已经解决了问题,在网络层 IP 地址可以用作网络中主机的唯一标识,传输层的"协议+端口"可用作主机应用的唯一标识,因此利用三元组(IP地址、协议、端口)就可以标识网络应用了,网络应用间可以用三元组作为标志和其他应用进行交互,socket 通信大致如下:
    在这里插入图片描述
    如图所示,应用程序进程在网络间的通信全部通过 socket 与底层协议交互,进行网络通信,但是 socket 并没有层的概念,它只是一种设计模式(软件抽象层),方便编程而已。

    编程流程

    socket 编程的底层实现是基于 TCP 和 UDP 的,因此其编程的流程也是围绕着这两个协议的客户端、服务端来进行的,大致流程如下图:
    在这里插入图片描述

    socket函数

    在实现上述功能的过程中,要用到很多接口函数,这一节就针对这些接口函数作详细解释。
    1、socket()
    这个函数作用是创建一个 socket 的操作对象,它被用作 socket 描述符的唯一标识(相当于文件描述符),在本地我们可以用这个对象进行文件操作,在主机远程连接时则可以用于建立连接、收发数据。
    2、bind()
    这是服务器端特有的接口函数,把 socket 对象和服务器的 IP 地址、开放端口绑定在一起,在 listen() 的调用下提供服务,客户端可以通过这个来连接服务器。但是客户端是没有 bind() 绑定地址和端口的,因为客户端不用发起监听,在客户端是在调用 connect() 时由系统随机生成一个。
    3、listen()
    也是服务器端特有的一个接口函数,作用是监听一个端口是否有数据发送过来,函数工作的时候会调用 bind() 函数,获取里面的套接字、地址和端口信息,如果有指向这个套接字描述符、本服务器地址和正在监听的这个端口的连接发送过来,则会让其通过并开始建立连接。
    4、connect()
    这个函数接口是 TCP 客户端特有的,用于向服务器发起连接建立请求。只要在 connect() 的参数中输入目标服务器的地址和端口,就会向目标发起连接请求,在服务端收到请求后就会调用 accept() 开始自动进行三次握手,从而建立连接。
    5、accept()
    这个函数接口是 TCP 服务端特有的,当 listen() 监听到请求后就会调用这个函数去建立连接,也就是说,只要这个函数执行成功,与客户端的连接就建立完成,并且可以互相传输数据了。
    6、recv(),recvfrom()
    这两个函数接口是用来接收数据的,recv() 方法对应 TCP 数据流,recvfrom() 则对应 UDP 数据流,因为 TCP 面向连接而 UDP 传输数据并不创建连接,所以要分这两种办法进行数据的接收。
    7、send(),sendto()
    和第 6 点的函数接口类似,但是用于发送数据的,和 recv()、recvfrom() 一起实现了网络中不同进程间的通信,其中 send() 对应 TCP 的传输方式,sendto() 对应的是 UDP 的传输方式。
    8、read(),write()
    这两个函数其实是通用的 I/O 读写操作,可以用来读写本地的文件,自然也可以用于网络间的读写操作。
    9、close()
    当客户端和服务端建立连接并处理完业务后,就要关闭相应的 socket 描述符以节省系统资源。在调用 close() 后,该 socket 描述字的引用计数 -1,不能够再由对应的调用进程使用,但是只有当引用计数=0 的时候,才会触发 TCP 客户端向服务端发起终止连接的请求。

    协议

    既然是通过底层协议进行信息传递,那么肯定少不了 OSI 七层模型:
    科来公司网络通信协议图(部分)
    现在有很多文章都讲得比较详细了,这里就只列出一些 socket 编程会用到的协议。

    TCP

    TCP 协议是一种面向连接的、可靠的、基于字节流的传输层通信协议,是为了互联网上提供可靠的端到端字节流而专门设计的,因此 TCP 协议做了一些规定:数据分片、到达确认、超时重发、滑动窗口、失序处理、重复处理、数据校验。
    作为可靠传输的一种协议,它有以下特点:
    1.基于流的方式
    2.面向连接
    3.网络不佳时尽量降低系统由于重传带来的带宽开销
    4.连接维护面向通信的两个端点
    在连接上,因为是可靠的,所以在建立连接的时候会进行三次握手,断开连接的时候则会进行四次挥手,在 socket 编程中体现如下:
    在这里插入图片描述
    在 socket 编程中,因为可靠性,TCP 是用的最多的连接协议,就连 http 协议也是基于 TCP 的。
    当两台主机要建立 TCP 连接时,客户端要向服务端发送 SYN 包发起连接请求,服务端收到 SYN 包后获取到客户端地址然后响应一个 SYN+ACK 包进行确认,表示接受连接,客户端收到这个确认包后也会返回一个用于确认的 ACK,到这里连接就建立完成了,接下来就可以传输数据了;
    如图所示,TCP 为了保证可靠性和降低开销,每次传输的数据是分片传输的,第一个分片会告诉服务端这一次有多少个分片要传输,传输序号为最后一个的分片则会告诉服务端数据传输完毕,服务端每接收一次数据包就会响应一个 ACK 确认,反过来也一样;
    在断开连接的时候则要经过四次挥手,断开连接的发起方可以是客户端也可以是服务端,其中一方发送 FIN+ACK 包告诉另一端数据传输完毕,询问是否能够断开连接,另一端收到后响应一个 ACK ,如果数据未接收完成,则通过这个 ACK 告诉对方未接收完成,暂时不要断开连。若数据传输完毕,则会发送 FIN 给信息发送方,告诉对方数据接收完成,准备好关闭连接了,另一端接收到 FIN 包后响应一个 ACK,同时状态变成 TIME_WAIT,接收方收到 ACK 确认后就断开连接,发送端等待 2msl 后若没收到接收端新的信息也会断开连接。
    上面的原理看起来很复杂,但是在 socket 层面就简化了很多,双方在连接前都要先建立好套接字,服务端还要开启监听,准备工作就完成了。客户端用 connect() 向服务端发起连接请求,服务端监听到请求后用 accept() 建立连接,这样三次握手就完成了;接下来连接双方都可以用 recv() 方法和 send() 方法进行数据的收发;数据传输完成后直接调用 close() 方法就可以完成四次挥手从而断开连接。

    UDP

    UDP 协议和 TCP 一样用来处理数据包,并且都位于传输层,不同的是 UDP 提供面向事务的简单不可靠信息传送服务,也就是说 UDP 协议的数据包发送后是没法知道是否安全、完整到达的,而且也不提供向 TCP 那样分片、重传、确认等功能,但是有个优点就是传输性能比 TCP 要高很多,毕竟不用分配资源去保证可靠性。因此在一些条件下 UDP 传输会更加实用。
    在 socket 编程中,用 UDP 协议传输数据也非常简单,客户端和服务端双方分别绑定套接字,服务端开始监听,客户端用 sendto() 直接发送数据,然后调用 close() 关闭数据出口,服务端则用 recvfrom() 接收;一次 UDP 数据传输就结束了。虽然 UDP 传输非常节省资源,但是会存在各种问题,因此在编程的时候要注意:一个 UDP 包允许报文长度 <512 字节,而 TCP 报文允许 >512 字节。

    DNS

    DNS 协议即地址解析协议,作用是将域名和 IP 地址互相转换,因为是基于 TCP、UDP 协议工作的,因此可以通过 socket 编程来实现其中的一些功能。在这之前我们先简单了解一下 DNS:
    首先,DNS(域名系统)是一个分布式数据库,被用来维护系统内每个主机名和 IP 的对应关系,用户输入域名时会自动查询 DNS 服务器,由服务器检索数据库,返回相应的 IP 地址;
    如果指定的 DNS 服务器没有记录,则会向上一层次的 DNS 服务器发起查找请求,各逻辑的树形结构(域名空间结构)如下图:
    在这里插入图片描述
    在解析请求时,如果本地(hosts文件)没有目标信息,就会去询问其他 DNS 服务器,这个过程是逐级提交的,其由高到低的层次划分可以分为下面几大类:

    分类作用
    根域名服务器最高层次的域名服务器,全世界仅13台,负责管理顶级域名
    顶级域名服务器负责管理在该顶级域名服务器下注册的二级子域
    权威域名服务器负责一个区的域名解析工作
    本地域名服务器当主机发起DNS查询请求时第一个查询的对象,一般为主机hosts文件/本地DNS服务器

    当其他 DNS 服务器返回查询结果时,该 DNS 服务器会把结果记录在本地缓存中,成为 DNS 缓存。
    查询方式分为两种:
    1.递归查询:在该模式下 DNS 服务器接收到客户机请求,必须使用一个准确的查询结果回复客户机。如果 DNS 服务器本地没有存储查询 DNS 信息,那么该服务器会询问其他服务器,并将返回的查询结果提交给客户机;
    2.迭代查询:当客户机发送查询请求时,DNS 服务器并不直接回复查询结果,而是告诉客户机另一台 DNS 服务器地址,客户机再向这台 DNS 服务器提交请求,依次循环直到返回查询的结果为止。
    基于这些理论,我们可以利用 socket 构造 DNS 查询请求,甚至可以把连接产生的 TCP 流量封装到 DNS 查询里,实现内网穿透。

    HTTP

    HTTP 协议(超文本传输协议)是现在互联网中最常用的一种网络协议,是一个标准的请求-应答模型(B/S),也就是说通信过程永远都是客户端发起请求,服务器返回响应信息,当然,也是基于 TCP 协议进行通信的。在客户机与服务器建立连接后,浏览器可以向 web 服务器发送请求并显示收到的网页,当用户在浏览器地址栏中输入一个 URL 时就会向 web 服务器发出 HTTP 请求,信息包括请求修饰符、客户端信息、提交的数据等,web 服务器接收到请求后对其进行处理并响应,响应的内容包括响应状态码、协议版本、服务器的部分信息、实体信息等,这些内容以 HTTP 规定的格式送回给客户端浏览器,浏览器对其进行显示。另外,HTTP 协议是无状态协议,即对事务处理没有记忆能力,在服务器不需要先前信息时应答速度就会很快。
    在 socket 编程中也遵循这个模型,分为客户端、服务端,客户端可以构造请求,发送数据给服务器,服务端可以发布静态/动态资源,供客户端获取,或者提供 I/O 接口,进行数据交互,也可以通过连接数据库,实现数据存储、查询等功能。
    其工作流程如下:
    1.浏览器根据域名解析 IP 地址;
    2.客户端通过浏览器与 web 服务器建立一个 TCP 连接;
    3.客户端向服务端发起请求;
    4.服务端响应客户端的 HTTP 请求,返回 html 代码;
    5.客户端解析 html 代码,请求资源;
    6.资源下载完毕后关闭 TCP 连接,浏览器对页面进行渲染然后呈现给用户。
    客户端根据服务器的设置发起的请求有很多种,下面列出一些常见的请求方式:

    方法作用
    GET申请获取资源
    POST客户端向服务器提交数据的方法
    HEAD申请获取响应的头部信息
    PUT用于上传资源
    DELETE用于删除资源
    TRACE用于返回原始请求内容,可用来查看中间服务器对http请求的影响
    OPTIONS用于查看服务器对特定URL都支持哪些请求
    CONNECT用于代理服务器,可把请求的连接转换成隧道
    PATCH对资源做部分修改

    每次请求的请求头都会附加一些信息,补充了请求的附加内容、客户端信息、相应内容相关优先级信息,下面是一些常见的请求头信息:

    头部字段名说明
    Accept用户代理可处理的媒体类型
    Accept-Charset优先的字符集
    Accept-Encoding优先的内容编码
    Accept-Language优先的语言
    Authorizationweb认证信息
    Expect期待服务器的特定行为
    From用户邮箱地址
    Host请求资源所在的服务器
    Proxy-Authorization代理服务器要求客户端的认证信息
    Range实体的字节范围请求
    Referer对请求中uri的原始获取方式
    TE传输编码优先级
    User-Agent浏览器信息

    而响应头则补充了资源内容更新时间等与实体有关的信息

    头部字段名说明
    Accept-Ranges是否接收字节范围的请求
    Age资源创建时间
    ETag资源匹配信息
    Location让客户端重定向到某uri
    Proxy-Authenticate代理服务器对客户端的认证信息
    Retry-After对再次请求的发起时机要求
    Server服务器的banner信息
    Vary代理缓存的管理信息
    WW-Authenticate服务器对客户端的认证信息

    实体资源的头部:

    头部字段名说明
    Allow资源可支持的http方法
    Content-Encoding适用的编码方式
    Content-Language优先语言
    Content-Length网页资源的大小
    Content-Location替代对应资源的uri
    Content-MD5资源的md5值
    Content-Range资源的位置范围
    Content-Type接收的数据格式类型
    Expires资源过期的时间
    Last-Modified资源最后修改日期

    除了上面的特征头部字段,还有通用的头部字段:

    头部字段名说明
    Cache-Control进行缓存操作的工作机制
    Connection控制不在转发给代理的首部字段,管理持久连接
    Date创建报文的时间
    Pragma编译报文指令
    Transfer-Encoding指定主体传输的编码方式
    Upgrade用于检测HTTP及其他协议是否可使用更高的版本进行通信
    Via代理相关信息
    Warning报错通知

    HTTPS

    HTTPS 是加密的 HTTP 通道,因为 HTTP 传输是明文的,存在信息泄露的风险,因此HTTPS就是在这基础上通过传输加密和身份认证保证了传输过程的安全性。
    HTTPS 其实并不是应用层的新协议,而是在 http 接口通过 SSL、TLS 来加密和认证的机制,其加密过程如下:
    1.客户端和服务器进行握手请求(https的握手)
    2.协商加密算法
    (客户端告诉服务器自己支持多少种加密组合,一个组合里面有 对称、非对称、hash、密钥交换算法,服务器选择自己支持的加密强度最高的一种)
    3.服务器发公钥证书给客户端
    4.客户端收到后在本地进行证书匹配(验证)
    (本地有根证书能解开的就说明这个公钥是那个根证书的公司签名的,没有能解开的就是不受信任的)
    5.客户端收到后在本地随机生成对称密钥(本次会话结束失效)
    6.客户端把生成的对称密钥用服务器给的公钥加密发给服务器
    7.服务器拿到用自己公钥加密的密文后用私钥解开,取得内容
    开始传输数据(两边都有加密密钥)
    8.客户端把加密的信息对应的hash值加了密的hash值发给服务器
    (明文信息用对称密钥加密,然后做hash计算,生成固定长度的hash值,用得到的公钥证书里的公钥对这个hash进行加密,生成hash值(给hash加密))
    9.服务器拿到这3部分信息后,用自己的私钥解开由自己公钥加了密的hash值,和客户端发的对应的hash值做比较,如果相同就表示没被篡改,再用客户端发的对称密钥解开加密的信息,再做hash计算,计算出的hash值和对应的hash值做比较,相同的话表示数据完整性没被破坏(身份验证)
    10.服务器开始接收数据
    在 socket 编程中也是可以实现 https,只是除了基本的 http 模块外还需要导入 SSL 相关的模块,编程的流程大致如下:
    在这里插入图片描述
    在这里插入图片描述
    如果有不对的地方,还请各位大佬指出 ^ _ ^


    相关文章:
    多线程编程概念
    Golang socket 编程
    Python socket 编程
    PHP socket 编程
    Java socket 编程

    展开全文
  • 本篇文章给大家带来的内容是关于socket编程的实现过程,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。1.socket 服务器搭建实例化socket服务器,循环获取请求package com.orange.util;import java...

    本篇文章给大家带来的内容是关于socket编程的实现过程,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

    1.socket 服务器搭建

    实例化socket服务器,循环获取请求package com.orange.util;

    import java.io.IOException;

    import java.net.ServerSocket;

    import java.net.Socket;

    import java.util.Timer;

    import java.util.TimerTask;

    import java.util.concurrent.Executors;

    import java.util.concurrent.ScheduledExecutorService;

    import java.util.concurrent.TimeUnit;

    /**

    * socket服务器

    *

    * @author Chengjq

    *

    */

    public class SocketServer {

    public static int count = 0;

    public static void main(String[] args) {

    // TODO 自动生成的方法存根

    int port = 4404;

    // 首先直接创建serversocket

    ServerSocket serverSocket = null;

    Socket socket = null;

    try {

    serverSocket = new ServerSocket(port);

    System.out.println("启动socketServer成功,等待客户端的连接");

    while (true) {

    socket = serverSocket.accept();

    System.out.println("有新的客户端请求连接");

    SocketThread st = new SocketThread(socket);

    st.start();

    ChatManager.getChatManager().add(st);

    //启动定时任务,如果10s内没有进程

    /*Runnable runnable = new Runnable() {

    int clientNum = 0;

    public void run() {

    // task to run goes here

    clientNum = ChatManager.getChatManager().vector.size();

    System.out.println("剩余客户端数量:"+clientNum);

    if(clientNum ==0 ){

    System.out.println("连接超时,或者无客户端连接,关闭serverSocket");

    //关闭socket

    //.....

    }

    }

    };

    ScheduledExecutorService service = Executors

    .newSingleThreadScheduledExecutor();

    // 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间

    service.scheduleAtFixedRate(runnable, 2, 10, TimeUnit.SECONDS); */

    }

    } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    } finally {

    System.out.println("serverSocket已超时");

    try {

    socket.close();

    serverSocket.close();

    } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    }

    }

    SocketThread类实现多线程通信package com.orange.util;

    import java.io.BufferedReader;

    import java.io.IOException;

    import java.io.InputStreamReader;

    import java.io.PrintWriter;

    import java.net.ServerSocket;

    import java.net.Socket;

    /**

    * SocketThread实现多线程通信

    *

    * @author Administrator

    *

    */

    public class SocketThread extends Thread {

    ServerSocket serverSocket = null;

    Socket socket = null;

    public SocketThread(ServerSocket serverSocket,Socket socket) {

    super();

    this.serverSocket = serverSocket;

    this.socket = socket;

    }

    public SocketThread(Socket socket) {

    super();

    this.socket = socket;

    }

    public void out(String out) {

    try {

    socket.getOutputStream().write(out.getBytes("utf-8"));

    } catch (IOException e) {

    e.printStackTrace();

    }

    }

    public void publish(String out){

    ChatManager.getChatManager().publish(this, out);

    }

    @Override

    public void run() {

    // TODO Auto-generated method stub

    BufferedReader socketIn = null;

    PrintWriter socketOut = null;

    String inMess = null;

    try {

    socketIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));

    socketOut = new PrintWriter(socket.getOutputStream());

    while (true) {

    inMess = socketIn.readLine();

    publish(inMess);

    if("bye".equals(inMess)){

    ChatManager.getChatManager().remove(this);

    }

    }

    } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    } finally {

    try {

    System.out.println("已结束当前会话");

    socketOut.close();

    socketIn.close();

    socket.close();

    } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    }

    }

    单例Chatmanage,对所有客户端线程管控处理package com.orange.util;

    import java.util.Vector;

    public class ChatManager {

    // 实现单例化

    private ChatManager() {

    };

    private static final ChatManager cm = new ChatManager();

    public static ChatManager getChatManager() {// 返回值为ChatManager

    return cm;

    }

    // 单例化完成

    Vector vector = new Vector();

    public void add(SocketThread st) {// 为当前集合添加SocketThread对象

    vector.add(st);

    }

    public void remove(SocketThread st) {// 当前客户端关闭连接

    vector.remove(st);

    }

    public void removeall() {// 关闭所有连接

    for (int i = 0; i < vector.size(); i++) {// 遍历所有的线程

    SocketThread csChatSocket = vector.get(i);

    if(csChatSocket!=null){

    vector.remove(csChatSocket);

    }

    }

    }

    // 某一个线程向其他的客户端发送信息

    public void publish(SocketThread st, String out) {

    for (int i = 0; i < vector.size(); i++) {// 遍历所有的线程

    SocketThread csChatSocket = vector.get(i);

    if (csChatSocket != st)// 判断不是当前线程就发送此消息

    csChatSocket.out(out + "\n");

    }

    }

    // 向当前线程发信息

    public void publish_present(SocketThread st, String out) {

    st.out(out + "\n");

    }

    }

    至此,服务器搭建完成

    2.客户端(创建两个客户端)

    客户端1(监听指定服务器,通过控制台输入消息进行服务器与客户端以及客户端之间的通信,)package com.orange;

    import java.io.BufferedReader;

    import java.io.IOException;

    import java.io.InputStreamReader;

    import java.io.PrintWriter;

    import java.net.Socket;

    import java.net.UnknownHostException;

    /**

    * 客户端1

    * @author Chengjq

    *

    */

    public class SocketClient1 {

    @SuppressWarnings("static-access")

    public static void main(String[] args) {

    try {

    //初始化客户端

    Socket socket = new Socket("127.0.0.1", 4404);

    BufferedReader readline = new BufferedReader(new InputStreamReader(System.in));

    //获取输出打印流

    PrintWriter socketOut = new PrintWriter(socket.getOutputStream());

    String outTemp = null;

    System.out.println("开始准备向服务器端发起请求---\n自己:");

    // 已启动连接socket服务器,准备实时接收来自其他客户端的消息

    GetMess getMess = new GetMess(socket);

    getMess.start();

    // 通过控制台发送消息给其他客户端,以“bye”为结束语

    while ((outTemp = readline.readLine()) != null) {

    //发送信息

    socketOut.println(outTemp);

    socketOut.flush();

    if("bye".equals(outTemp)){

    break;

    }

    }

    getMess.currentThread().interrupt();

    //依次关闭各种流

    readline.close();

    socketOut.close();

    socket.close();

    } catch (UnknownHostException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    }

    客户端2package com.orange;

    import java.io.BufferedReader;

    import java.io.IOException;

    import java.io.InputStreamReader;

    import java.io.PrintWriter;

    import java.net.Socket;

    import java.net.UnknownHostException;

    public class SocketClient2 {

    @SuppressWarnings("static-access")

    public static void main(String[] args) {

    try {

    //初始化客户端

    Socket socket = new Socket("127.0.0.1", 4404);

    BufferedReader readline = new BufferedReader(new InputStreamReader(System.in));

    //获取输出打印流

    PrintWriter socketOut = new PrintWriter(socket.getOutputStream());

    String outTemp = null;

    System.out.println("开始准备向服务器端发起请求---\n自己:");

    // 已启动连接socket服务器,准备实时接收来自其他客户端的消息

    GetMess getMess = new GetMess(socket);

    getMess.start();

    // 通过控制台发送消息给其他客户端,以“bye”为结束语

    while ((outTemp = readline.readLine()) != null) {

    //发送信息

    socketOut.println(outTemp);

    socketOut.flush();

    if("bye".equals(outTemp)){

    break;

    }

    }

    getMess.currentThread().interrupt();

    //依次关闭各种流

    readline.close();

    socketOut.close();

    socket.close();

    } catch (UnknownHostException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    }

    GetMess(多线程处理获取其他客户端的消息并且展示)package com.orange;

    import java.io.BufferedReader;

    import java.io.IOException;

    import java.io.InputStream;

    import java.io.InputStreamReader;

    import java.net.Socket;

    public class GetMess extends Thread {

    Socket socket = null;

    public GetMess(Socket socket) {

    super();

    this.socket = socket;

    }

    @Override

    public void run() {

    // TODO Auto-generated method stub

    BufferedReader socketIn = null;

    try {

    InputStream is = socket.getInputStream();

    InputStreamReader isr = new InputStreamReader(is);

    socketIn = new BufferedReader(isr);

    String inTemp = null;

    while(true){

    inTemp = socketIn.readLine();

    if(inTemp != null && !"bye".equals(inTemp) ){

    System.out.println("好友:\n"+inTemp);

    }else{

    System.out.println("好友:\n已下线,关闭当前回话");

    break;

    }

    }

    } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }finally {

    try {

    Thread.currentThread().interrupt();

    socketIn.close();

    } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    }

    }

    ok,简单的sockte服务与客户端完成了

    先启动server

    在分别启动client

    5e4d8299a2eed28bfea9088aa9e8cd5d.png

    5756eed950b683e08327ae60d0bd946b.png

    2e56b40973d1a8a1f34963079fd2d8f6.png

    3a5c3e963d3167a917949af2993aa526.png

    输入结束bye,关闭当前会话

    9a69b7bceab1582ec36895947d6f2e5f.png

    展开全文
  • socket编程

    2021-07-06 09:46:27
    要学Internet上的TCP/IP网络编程,必须理解Socket接口。 tcp 服务器端程序: 1.用函数socket()创建一个socket; 2.用函数bind()绑定IP地址、端口号等信息到socket上; 3.用函数listen()设置最大连接数; 4.用...

    socket用于客户端与服务器之间通信的。
    socket接口是TCP/IP网络的api,Socket接口定义了许多函数或例程,程序员可以用它们来开发TCP/IP网络上的应用程序。要学Internet上的TCP/IP网络编程,必须理解Socket接口。

    tcp

    服务器端程序:
    1.用函数socket()创建一个socket;
    2.用函数bind()绑定IP地址、端口号等信息到socket上;
    3.用函数listen()设置最大连接数;
    4.用accept()接收客户端上来的连接;
    5.收发数据,用函数send,recv,read,write;
    6.关闭网络连接。

    客户端程序:
    1.用函数socket()创建一个socket;
    2.设置要连接的对方的ip地址和端口等属性;
    3.用connect()函数连接服务器;
    4.收发数据,用函数send,recv,read,write;
    5.关闭网络连接。

    udp

    服务器端程序:
    1.用函数socket()创建一个socket;
    2.设置服务器地址和监听端口,初始化要绑定的网络地址结构。
    3.用函数bind()绑定IP地址、端口号等信息到socket上;
    4.用recvfrom()函数接收客户端网络数据;
    5.用sendto()向客户端发送数据;
    6.使用close()关闭嵌套字,释放资源。

    客户端程序:
    1.用函数socket()创建一个socket;
    2.设置要连接的对方的ip地址和端口等属性,struct sockaddr;
    3.用recvfrom()函数接收客户端网络数据;
    4.用sendto()向客户端发送数据;
    5.使用close()关闭嵌套字,释放资源。

    展开全文
  • C语言SOCKET编程--超级完整 介绍 Socket 编程让你沮丧吗?从man pages中很难得到有用的信息吗?你想跟上时代去编Internet相关的程序,但是为你在调用 connect() 前的bind() 的结构而不知所措?等等… 好在我已经将...
  • 在网络通信中socket几乎无处不在,它...Python提供了socket模块,可以非常方便的进行socket编程。创建一个server socket使用socket方法创建一个新的socket,通常提供两个参数,第一个参数是address family, 第二个...
  • socket编程实验心得体会

    千次阅读 2021-03-09 19:50:00
    } 四、实验心得体会 通过本次实验的练习,熟悉了TCP/IP协议,对套接字等概念有了深入的了解,对用Java语言实现Socket编程并实现客户端和服务器端的信息交互有了一定的了解。 JAVA编程心得 计算机3班 窦金霞 ...
  • 下图中,从编程的角度来看,客户端将数据发送给在客户端侧的Socket 对象,然后客户端侧的 Socket 对象将数据发送给服务端侧的 Socket 对象。Socket 对象负责提供通信能力,并处理底层的 TCP 连接/UDP 连接。对...
  • C语言socket编程的方法

    2021-05-20 07:49:44
    socket编程的教材网上搜罗下还是很多的,思路基本上也是一样的,程序分两部分客户端和服务器端,下面是小编为大家搜索整理的`C语言socket编程的方法,希望大家能有所收获,更多精彩内容请及时***应届毕业生考试网!...
  • 一、创建socket socket就是一个可读、可写、可控制、可关闭的文件描述符(整型数字) // 函数原型 int socket(int domain, int type, int protocol) //参数解释 domain:指定系统使用的协议。可以是TCP/IP协议族,...
  • linux socket编程总结

    2021-03-03 16:04:23
    今天系统复习一下socket编程,因为本人已经有了基本的网络和操作系统的知识,直接跳过很基本的背景知识介绍了。我理解的socket就是抽象封装了传输层以下软硬件行为,为上层应用程序提供进程/线程间通信管道。就是让...
  • springboot+netty实现socket编程 Java socket网络编程一直没有怎么接触到,虽然以前也自学过netty,但未在实际项目中使用过,始终感觉肤浅。最近看到lcnV4.0.2版本时,才算明白如何在实际springboot项目中如何使用...
  • 面向连接的Socket编程

    2021-09-29 16:53:08
    实验二 面向连接的Socket编程 一、 实验目的 1.了解Socket的工作原理、服务方式和类型。 2.了解Socket应用程序的框架结构及相关数据结构。 3.理解面向连接的Socket通信流程。 4.掌握使用WinSock函数编写面向连接的...
  • tcpsocket编程流程

    2021-07-19 01:32:34
    1.socket-创建套接字 2.bind-为套接字绑定地址信息 3.listen-服务端开始监听 listen(int sockfd,int backlog) listen的第二个参数backlog表示并发连接数,并发连接数是指服务端同一时间所能接收的客户端请求连接...
  • qt中socket编程

    2021-05-31 10:25:44
    使用网络编程要在pro文件下添加network,然后项目qmake,不执行可能会找不到socket头文件 然后是设计界面如下 头文件代码 #ifndef WIDGET_H #define WIDGET_H #include <QWidget> #inclu
  • Java Socket编程基础篇

    2021-02-27 19:09:00
    Java最初是作为网络编程语言出现的,其对网络提供了高度...Socket编程网络基础知识点:两台计算机间进行通讯需要以下三个条件IP地址、协议、端口号:IP地址:定位应用所在机器的网络位置。(比如家庭住址:北京市朝阳...
  • 用python实现socket编程

    2021-08-23 10:02:39
    建立网络通信连接至少要一对端口号(socket),socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口;HTTP是轿车,提供了封装或者显示数据的具体形式;...
  • socket编程是网络常用的编程,我们通过在网络中创建socket关键字来实现网络间的通信,通过收集大量的资料,通过这一章节,充分的了解socket编程,文章用引用了大量大神的分析,加上自己的理解,做个总结性的文章。...
  • 本文实例讲述了Java基于Tcp协议的socket编程方法,分享给大家供大家参考。具体分析如下:以下是一对一的通信编程实现,后续会继续学习一个服务器监听多个客户端的实现。这里用到的主要步骤如下:第一步:以特定端口...
  • 计算机网络实验socket编程实验三 socket套接字编程实验一、Sockets编程基础知识网络编程就是通过计算机网络与其他程序进行通信的程序,Socket编程是网络编程的主流工具。Socket API是实现进程间通信的一种编程设施,...
  • Socket编程利用TCP协议的实验报告》由会员分享,可在线阅读,更多相关《Socket编程利用TCP协议的实验报告(8页珍藏版)》请在人人文库网上搜索。1、Socket 编程报告( TCP/IP 协议)实验目的通过 C+ 来实现 TCP/IP ...
  • #re: 多线程Java Socket编程示例回复更多评论2010-05-09 14:05 by 诗特林fans服务器端:public class MultiThreadServer {private int port=8821;private ServerSocket serverSocket;private ExecutorService ...
  • 网络编程:socket编程步骤

    千次阅读 2021-08-22 14:41:57
    Sockt服务器和客户端的开发步骤 1.创建套接字 2.为套接字添加信息(IP地址和端口号) 3.监听网络连接
  • C语言实现Socket编程

    2021-05-22 01:04:18
    tcpsrv.c的内容如下: #include #include #define RECEIVE_MAX_LENGTH 100 #define SEND_MAX_LENGTH 100 void main() { WORD wVersionRequested;... } SOCKET socketClient = socket(AF_INET,SOCK_STREAM
  • 实验三 面向非连接的基础Socket编程 一、 实验目的 1.了解面向非连接的Socket通信流程。 2.掌握使用WinSock函数编写面向非连接的网络应用程序的方法。 二、实验内容 利用数据报套接字编程实现网络通信程序。要求如下...
  • python异步socket编程之一浏览次数:发布时间:2014-12-10 11:08异步网络能极大地提高程序的并行处理能力,所以写了一个专题来总结python中的异步通信。一、同步client与同步server的通信1.1. 《python的socket通信...
  • 摘要基于Socket编程的基本原理和开发流程,本文设计并实现了基于单播和组播的多人聊天工具,以及基于组播的视频会议软件。本次Socket网络可视化编程的开发平台为Python + Qt。通过对两款软件的开发,深入理解了...
  • socket编程(java实现)

    2021-05-10 22:06:11
    socket编程 socket,又称套接字,是在不同的进程间进行网络通讯的一种协议、约定或者说是规范。 对于socket编程,它更多的时候像是基于TCP/UDP等协议做的一层封装或者说抽象,是一套系统所提供的用于进行网络通信...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 317,203
精华内容 126,881
关键字:

scoket编程