`
chenyinghg
  • 浏览: 33719 次
  • 性别: Icon_minigender_2
  • 来自: 惠州
社区版块
存档分类
最新评论

ssl 与 socket

 
阅读更多

第一次接触到这个问题是由于tornado。在tornado.netutil中发现将socket包装成ssl socket的函数,原来可以这样写。恩, 学识浅薄。

Socket

socket对TCP/IP协议的封装和应用, 是程序员层面的。关于协议, 推荐豆瓣阅读上的《协议森林》,很不错, 适合了解一下。

python socket:

__init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None)

           family是协议域, 又称协议族。 协议族决定socket的地址类型,在通信中必须采用对应地址

                常用的有:

                AF_INET                        决定要用ipv4的地址32位, 与端口号(16位的组合)

                AF_INET6

                AF_LOCAL 或称AF_UNIX UNIX域socket                    AF_UNIX决定要用一个绝对路径作为地址

                AF_ROUTE

           type是socket的类型

                常用的有:

                SOCK_STREAM

                SOCK_DGRAM

                SOCK_RAW

                SOCK_PACKET

                SOCK_SEQPACKET

            proto指定协议

                IPPROTO_TCP   tcp协议

                IPPROTO_UDP  udp协议

                IPPROTO_SCTP   sctp协议

                IPPROTO_TIPC    tipc协议

 个人认为, socket就是对传输协议的封装, 使用sockt可以不用关注tcp等协议数据的处理,更接近程序员。

socket还可以结合epoll使用, 参考http://blog.csdn.net/songfreeman/article/details/51179213:

#!/usr/bin/env python
import select
import socket

response = b''

serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind(('0.0.0.0', 8080))
serversocket.listen(1)
# 因为socket默认是阻塞的,所以需要使用非阻塞(异步)模式。
serversocket.setblocking(0)

# 创建一个epoll对象
epoll = select.epoll()
# 在服务端socket上面注册对读event的关注。一个读event随时会触发服务端socket去接收一个socket连接
epoll.register(serversocket.fileno(), select.EPOLLIN)

try:
    # 字典connections映射文件描述符(整数)到其相应的网络连接对象
    connections = {}
    requests = {}
    responses = {}
    while True:
        # 查询epoll对象,看是否有任何关注的event被触发。参数“1”表示,我们会等待1秒来看是否有event发生。
        # 如果有任何我们感兴趣的event发生在这次查询之前,这个查询就会带着这些event的列表立即返回
        events = epoll.poll(1)
        # event作为一个序列(fileno,event code)的元组返回。fileno是文件描述符的代名词,始终是一个整数。
        for fileno, event in events:
            # 如果是服务端产生event,表示有一个新的连接进来
            if fileno == serversocket.fileno():
                connection, address = serversocket.accept()
                print('client connected:', address)
                # 设置新的socket为非阻塞模式
                connection.setblocking(0)
                # 为新的socket注册对读(EPOLLIN)event的关注
                epoll.register(connection.fileno(), select.EPOLLIN)
                connections[connection.fileno()] = connection
                # 初始化接收的数据
                requests[connection.fileno()] = b''

            # 如果发生一个读event,就读取从客户端发送过来的新数据
            elif event & select.EPOLLIN:
                print("------recvdata---------")
                # 接收客户端发送过来的数据
                requests[fileno] += connections[fileno].recv(1024)
                # 如果客户端退出,关闭客户端连接,取消所有的读和写监听
                if not requests[fileno]:
                    connections[fileno].close()
                    # 删除connections字典中的监听对象
                    del connections[fileno]
                    # 删除接收数据字典对应的句柄对象
                    del requests[connections[fileno]]
                    print(connections, requests)
                    epoll.modify(fileno, 0)
                else:
                    # 一旦完成请求已收到,就注销对读event的关注,注册对写(EPOLLOUT)event的关注。写event发生的时候,会回复数据给客户端
                    epoll.modify(fileno, select.EPOLLOUT)
                    # 打印完整的请求,证明虽然与客户端的通信是交错进行的,但数据可以作为一个整体来组装和处理
                    print('-' * 40 + '\n' + requests[fileno].decode())

            # 如果一个写event在一个客户端socket上面发生,它会接受新的数据以便发送到客户端
            elif event & select.EPOLLOUT:
                print("-------send data---------")
                # 每次发送一部分响应数据,直到完整的响应数据都已经发送给操作系统等待传输给客户端
                byteswritten = connections[fileno].send(requests[fileno])
                requests[fileno] = requests[fileno][byteswritten:]
                if len(requests[fileno]) == 0:
                    # 一旦完整的响应数据发送完成,就不再关注写event
                    epoll.modify(fileno, select.EPOLLIN)

            # HUP(挂起)event表明客户端socket已经断开(即关闭),所以服务端也需要关闭。
            # 没有必要注册对HUP event的关注。在socket上面,它们总是会被epoll对象注册
            elif event & select.EPOLLHUP:
                print("end hup------")
                # 注销对此socket连接的关注
                epoll.unregister(fileno)
                # 关闭socket连接
                connections[fileno].close()
                del connections[fileno]
finally:
    # 打开的socket连接不需要关闭,因为Python会在程序结束的时候关闭。这里显式关闭是一个好的代码习惯
    epoll.unregister(serversocket.fileno())
    epoll.close()
    serversocket.close()

 SSL

ssl个人喜欢把它理解为一种加密协议。采用对称算法进行加密。SSL协议的版本只有1和2只提供服务器认证, 版本3添加了客户端认证,此认证同时需要客户端和服务器的数字证书。

盗图:参考https://www.wosign.com/Basic/howsslwork.htm


 

tornado中将socket包装成ssl的代码:

#定义SSL的一些参数
_SSL_CONTEXT_KEYWORDS = frozenset(['ssl_version', 'certfile', 'keyfile',
                                   'cert_reqs', 'ca_certs', 'ciphers'])


def ssl_options_to_context(ssl_options):
    """尝试将ssl的option参数转化为ssl.SSLContext对象"""
    if isinstance(ssl_options, dict):
       # 要求ssl option的参数必须是_SSL_CONTEXT_KEYWORDS预定义的
        assert all(k in _SSL_CONTEXT_KEYWORDS for k in ssl_options), ssl_options
    if (not hasattr(ssl, 'SSLContext') or
            isinstance(ssl_options, ssl.SSLContext)):
        return ssl_options
    context = ssl.SSLContext(
        ssl_options.get('ssl_version', ssl.PROTOCOL_SSLv23))
    if 'certfile' in ssl_options:
        context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))
    if 'cert_reqs' in ssl_options:
        context.verify_mode = ssl_options['cert_reqs']
    if 'ca_certs' in ssl_options:
        context.load_verify_locations(ssl_options['ca_certs'])
    if 'ciphers' in ssl_options:
        context.set_ciphers(ssl_options['ciphers'])
    if hasattr(ssl, 'OP_NO_COMPRESSION'):
        context.options |= ssl.OP_NO_COMPRESSION
    return context


def ssl_wrap_socket(socket, ssl_options, server_hostname=None, **kwargs):
    #包装函数
    context = ssl_options_to_context(ssl_options)
    if hasattr(ssl, 'SSLContext') and isinstance(context, ssl.SSLContext):
        if server_hostname is not None and getattr(ssl, 'HAS_SNI'):
            return context.wrap_socket(socket, server_hostname=server_hostname,
                                       **kwargs)
        else:
            return context.wrap_socket(socket, **kwargs)
    else:
        return ssl.wrap_socket(socket, **dict(context, **kwargs))  

 
 

 

  • 大小: 32.2 KB
分享到:
评论

相关推荐

    易语言SSL_Socket通信模块源码

    《易语言SSL_Socket通信模块源码解析与应用》 在信息技术日新月异的今天,网络通信的安全性越来越受到重视。SSL(Secure Sockets Layer)协议作为网络安全传输的重要手段,广泛应用于各种网络服务中。易语言,作为...

    SSL+socket 详解-概念

    5. 通过SSLContext获取SSLServerSocketFactory或SSLSocketFactory来创建SSLServerSocket或SSLSocket,进行安全的通信。 由于SSL/TLS协议的复杂性,开发人员在使用JSSE进行SSL/TLS编程时需要深入理解相关的加密原理...

    Java中SSLSocket应用教程和代码

    在Java编程语言中,SSLSocket(Secure Sockets Layer Socket)是用于实现安全网络通信的重要组件,它基于SSL/TLS协议栈,为应用程序提供加密的数据传输服务。本教程将深入探讨Java中的SSLSocket应用,包括其基本概念...

    SSL-Socket-Client_socket实现https_socketssl_SSLSOCKET_https_

    6. **连接SSL**:将SSL结构体与Socket绑定,使用`SSL_set_fd()`函数设置Socket描述符。然后,调用`SSL_connect()`来建立SSL连接,这会进行SSL握手,包括证书交换、密钥协商等。 7. **发送和接收数据**:SSL连接建立...

    Java SSLSocket的使用

    与普通`Socket`类似,`SSLSocket`提供了`getInputStream()`和`getOutputStream()`方法,用于读取和写入加密的数据。需要注意的是,由于SSL握手的存在,必须等待握手完成才能进行读写操作,否则可能会抛出异常。 6....

    SSLSocket通信Demo android版

    4. **建立连接**:使用SSLSocketFactory创建SSLSocket实例,并通过其建立与服务器的连接。注意,SSLSocket在建立连接时会进行SSL握手,验证对方的身份。 5. **数据传输**:连接建立后,就可以通过SSLSocket的输入...

    基于ssl的Java的socket网络通信

    SSLSocket socket = (SSLSocket) sf.createSocket("server_address", server_port); ``` 然后,我们可以通过SSLSocket进行正常的Socket通信,包括输入流和输出流的读写。在开始通信之前,会进行SSL握手,这是一个...

    利用C#实现SSLSocket加密通讯的方法详解

    「C#实现SSLSocket加密通讯方法详解」 在网络通讯中,安全性是一个非常重要的方面,而SSL/TLS协议则是最常用的加密通讯协议之一。C#作为一个强大的编程语言,可以轻松地实现SSL/TLS协议的加密通讯。下面将详细介绍...

    Java ssl socket 双向认证

    Java SSL(Secure Socket Layer)套接字是一种用于在两个应用程序之间建立安全通信通道的协议,主要目的是为了确保数据传输的安全性。SSL通过使用加密技术来保护数据,防止未经授权的访问和篡改。在Java中,我们可以...

    java 采用ssl的socket交互

    详细介绍了java如何使用SSL来进行socket通信了 最主要的是介绍了如何使用keytool来生成.keystore文件 ps:设置一分是希望那些刚入门或则对csdn访问不多的朋友 多花点时间 表面上市搞积分 事实上是有帮助的。 如果你...

    cli.rar_Openssl socket_openssl ssl_socket ssl_ssl

    5. **将SOCKET与SSL上下文关联**:使用`SSL_CTX_new()`创建的SSL上下文,通过`SSL_new()`创建一个SSL对象,并用`SSL_set_fd()`将SOCKET描述符绑定到SSL对象。 6. **SSL握手**:执行SSL/TLS的握手过程,这包括证书...

    基于 MINA 的 TLS/SSL NIO Socket 实现(二)

    在本篇博文中,我们将深入探讨如何利用Apache MINA库实现基于TLS/SSL的NIO(非阻塞I/O)Socket通信。MINA是一个高度可扩展的网络应用框架,广泛用于构建高性能、高并发的网络应用程序,如服务器端的TCP和UDP服务。...

    android 7.0 SSLsocket

    SSLSocket sslSocket = (SSLSocket) socketFactory.createSocket(); sslSocket.setHostnameVerifier(hostnameVerifier); ``` 通过这样的配置,开发者可以确保在Android 7.0上,即使面对非标准的证书配置,也能正常...

    ssl socket加密传输

    - 设置Socket连接:`SSL_set_fd()`将Socket描述符与SSL对象关联。 - 进行SSL握手:调用`SSL_connect()`或`SSL_accept()`进行客户端或服务器端的握手过程。 - 数据传输:使用`SSL_read()`和`SSL_write()`进行加密...

    VC工程,ssl通讯socket,服务端和客户端,简单易懂。

    4. 创建Socket连接:与服务器建立普通Socket连接。 5. 创建SSL连接对象:使用`SSL_new()`,关联到Socket。 6. SSL握手:调用`SSL_connect()`进行握手。 7. 数据传输:使用`SSL_read()`和`SSL_write()`进行加密通信。...

    Socket ssl 加密

    在Android中,通常使用java.net.SSLSocket和SSLSocketFactory类来实现SSL/TLS的Socket通信。 3. **生成BKS文件**: BKS(Bouncy Castle Keystore)是Android上常用的SSL证书存储格式。为了实现SSL加密,需要一个...

    ssl_socket.zip_SSL SOCKET_ca证书验证 ssl套接字通信_sSLSocket和socket_ssl通信

    ssl套接字通信服务端和客户段 ssl单向认证、双向认证

    封装了SSL 的 Socket 类 源码

    * MOD-NAME : sslsocket.h * LONG-NAME : * * AUTHOR : Martin Ziacek (martin.ziacek@pobox.sk) * DEPARTMENT : * TELEPHONE : * CREATION-DATE : 29/05/2001 15:27:01 * SP-NO : * FUNCTION : * ***********...

    SSLDemo安全Socket通信Demo

    **SSLDemo安全Socket通信Demo**是一个用于演示如何在C#编程环境中实现基于Socket的安全通信的应用程序。这个Demo深入展示了网络安全的重要概念,如数字签名、SSL(Secure Socket Layer)协议、非对称加密和对称加密...

Global site tag (gtag.js) - Google Analytics