简体   繁体   English

Python SSL Socket:从服务器和客户端接收和发送

[英]Python SSL Socket: receiving and sending from both server and client

OK, So I'm trying to get back and forth communication between server and client over an SSL socket connection. 好的,所以我试图通过SSL套接字连接在服务器和客户端之间来回通信。 What I thought would be the best way to do this would have been to implement 2 threads in each, each thread acting as a server and a client respectively.But when I implement this code (obviously using opposite corresponding ports in other server/client): 我认为最好的方法就是在每个中实现2个线程,每个线程分别充当服务器和客户端。但是当我实现这个代码时(显然在其他服务器/客户端使用相对的相应端口) :

#secserv.py

import socket
from OpenSSL import SSL
import threading
import time

class SecureIn(threading.Thread):
  context = SSL.Context(SSL.SSLv23_METHOD)
  context.use_privatekey_file('key')
  context.use_certificate_file('cert')

  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  s = SSL.Connection(context, s)
  s.bind(('', 5570))
  def run(self):
    while True:
      self.s.listen(5)
      (connection, address) = self.s.accept()
      print repr(connection.recv(5570))


class SecureOut(threading.Thread):
  time.sleep(6)
  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  s.connect(('localhost', 12345))
  sslSocket = socket.ssl(s)
  print repr(sslSocket.server())
  print repr(sslSocket.issuer())
  def run(self):
    sslSocket.write('Hello secure socket\n')

  s.close()


si = SecureIn()
si.start()
time.sleep(6)
so = SecureOut()
so.start()

I get this error: 我收到此错误:

Traceback (most recent call last):
  File "secserv.py", line 25, in <module>
    class SecureOut(threading.Thread):
  File "secserv.py", line 28, in SecureOut
    s.connect(('localhost', 12345))
  File "/usr/lib/python2.7/socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
socket.error: [Errno 111] Connection refused

Alternatively I have tried getting a standalone server to send even a broadcast message to all clients. 或者,我尝试使用独立服务器向所有客户端发送广播消息。 I've searched high and low, but I can't seem to find a working way to do it with SSL socket, only regular sockets. 我已经搜索了高低,但我似乎无法找到一种工作方式来使用SSL套接字,只有常规套接字。 When I try either s.write() or s.sendall() I get this error: 当我尝试s.write()s.sendall()我收到此错误:

Traceback (most recent call last):
  File "secserv.py", line 19, in <module>
    s.write('hello client\n')
OpenSSL.SSL.Error: [('SSL routines', 'SSL_write', 'uninitialized')]

from this code: 从这段代码:

import socket
from OpenSSL import SSL
context = SSL.Context(SSL.SSLv23_METHOD)
context.use_privatekey_file('key')
context.use_certificate_file('cert') 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s = SSL.Connection(context, s)
s.bind(('', 12345))
while True:
    s.listen(5) 
    (connection, address) = s.accept()
    print repr(connection.recv(12345))
    #This could also be s.sendall()
    s.write('hello client\n')

Please help me StackOverFlow, you're my only hope. 请帮我StackOverFlow,你是我唯一的希望。 I know this should be easy, but my brain is so strained at this point, I just can't think anymore. 我知道这应该很容易,但是我的大脑在这一点上非常紧张,我再也想不到了。

Also, I'm fairly new to python, so there is a large possibility that there's something about the way it operates/loads classes/etc, that I just don't get. 另外,我对python很新,所以很有可能它的操作方式/加载类/等等,我只是没有得到。

EDIT: OK, I know this code is bad. 编辑:好的,我知道这段代码很糟糕。 It isn't a product that's going to market, it will never be run live, this is just me trying to get a concept working, and that concept is: get server and client sending messages to each other over a python ssl connection. 它不是一个推向市场的产品,它永远不会在现场运行,这只是我试图让一个概念起作用,而这个概念是:让服务器和客户端通过python ssl连接向对方发送消息。

I know this is terrible code, but I just need to know how to get the server to send a message back, because whenever I try it I get the error at the end. 我知道这是可怕的代码,但我只需要知道如何让服务器发回消息,因为无论何时我尝试它都会在最后得到错误。

Your design seems to be misguided at many levels. 您的设计似乎在许多层面上都是错误的。

First, you do not need two sockets to send data in both directions; 首先,您不需要两个插槽来向两个方向发送数据; sockets are bidirectional. 套接字是双向的。

And you probably do not want to make a connection from the server back to the client—that might work in localhost testing, but once you deploy to the internet, most of the clients will be behind NAT routers, and won't have public addresses that you can connect to. 并且您可能不希望从服务器返回到客户端 - 这可能在localhost测试中起作用,但是一旦部署到Internet,大多数客户端将位于NAT路由器后面,并且不会有公共地址你可以连接到。

Meanwhile, your logic is very odd. 同时,你的逻辑很奇怪。 You start the connection in one direction, then sleep 6 seconds, then start the connection in the other direction. 您在一个方向上开始连接,然后睡6秒,然后在另一个方向上开始连接。 Why would you want to do that? 你为什么想这么做?

If the server calls its SecureOut before, or even around the same time, as the client calls its SecureIn , it will try to connect before there's anyone listening, which will get exactly the error you're seeing. 如果服务器调用其SecureOut之前,甚至在同一时间,作为客户端调用其SecureIn ,它会尝试连接有任何人听,这将让正是你所看到的错误了。

Also, you've got a very weird run loop for each thread: 此外,每个线程都有一个非常奇怪的运行循环:

def run(self):
    while True:
        self.s.listen(5)
        (connection, address) = self.s.accept()
        print repr(connection.recv(5570))

This only accepts one connection at a time, does a single read from it, then just leaks the connection, never talking to it again, and goes to get the next client. 这一次只接受一个连接,从中读取一次,然后泄漏连接,再也不与它通话,然后去获取下一个客户端。 (I'm also not sure if it is actually valid to call listen(5) again on a socket that's already listening, or what it does.) And of course there's no way it can ever finish. (我也不确定在已经正在收听的套接字上再次调用listen(5)是否真的有效。或者它的功能。当然,它无法完成。 (That's not quite true—if, eg, a client connects and then goes away before you call recv , you'll probably get an exception, which you don't catch, so your program will just exit…) Is that what you want? (这不是真的 - 例如,如果一个客户端连接然后在你调用recv之前消失,你可能会得到一个例外,你没有抓到,所以你的程序将退出...)这就是你想要的?

Also, why recv(5570) ? 另外,为什么recv(5570) That number is the max number of bytes to read, not the port number. 该数字是要读取的最大字节数,而不是端口号。

And why print the repr of a string? 为什么打印字符串的repr

Meanwhile, do you realize that recv , no matter what you pass for the buffer length, is never guaranteed to get an entire message (or to get only one message instead of two, if you had a client that ever sent more than one)? 同时,你是否意识到recv ,无论你为缓冲区长度传递什么,都不能保证获得整个消息(或者只获得一条消息而不是两条消息,如果你有一个客户端发送了多个消息)? It will almost certainly work that work on localhost, and with such a small message it will likely work most of the time on the internet, but not all the time. 它几乎可以肯定地在localhost上工作,并且通过这么小的消息它可能在互联网上大部分时间都可以工作,但不是所有的时间。

You also seem to be confused about the difference between class variables and instance variables, because you're setting a bunch of class variables in both SecureIn and SecureOut . 您似乎也对类变量和实例变量之间的区别感到困惑,因为您在SecureInSecureOut设置了一堆类变量。 This means that if you could ever have two instances of the class, they'd share the same SSL.Context , etc. Even if you don't need to have two simultaneous instances in real life, for testing you'll almost certainly want to create a new instance, and you'll want that to create a new socket, etc., not keep using the old one. 这意味着如果你有两个类的实例,它们会共享相同的SSL.Context等。即使你不需要在现实生活中同时拥有两个实例,为了测试你几乎肯定会想要创建一个新实例,你会想要创建一个新的套接字等,而不是继续使用旧的。 So instead of this: 所以不是这样的:

class SecureIn(threading.Thread):
  context = SSL.Context(SSL.SSLv23_METHOD)
  context.use_privatekey_file('key')
  context.use_certificate_file('cert')
  …

Do this: 做这个:

class SecureIn(threading.Thread):
  def __init__(self):
    self.context = SSL.Context(SSL.SSLv23_METHOD)
    self.context.use_privatekey_file('key')
    self.context.use_certificate_file('cert')
    …

(Or you could put that in the run method, of course.) (或者你可以把它放在run方法中,当然。)

Basically, this isn't likely to do anything useful, with or without SSL. 基本上,无论是否使用SSL,这都不太可能有用。 I would suggest you take a step back, go over some tutorials, and write something that works with plain-old TCP sockets, and then worry about how to SSL-ize it. 我建议你退后一步,阅读一些教程,并编写适用于普通TCP套接字的东西,然后担心如何对其进行SSL-ize。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Python套接字; 从客户端在服务器上接收发送 - Python sockets; sending from client receiving on server Python Sockets:客户端和服务器都互相发送和接收数据? - Python Sockets: Client and Server both sending and receiving data from each other? PHP服务器套接字从python客户端套接字接收连续数据 - Php server socket receiving continuous data from python client socket 将图像从套接字服务器(java)发送到套接字客户端(python) - sending Image from Socket server (java) to socket client (python) Python 3套接字客户端发送数据,而C ++套接字服务器接收带偏移量的数据? - Python 3 socket client sending data and C++ socket server receiving data with offset? Python 服务器不发送数据/客户端不接收 - Python Server not sending data/Client not receiving 使用python套接字发送,接收 - Sending, receiving with python socket 通过套接字/ ftp python从服务器向客户端发送文件 - Sending files to client from server via socket/ftp python 使用python中的套接字编程将视频流从服务器发送到客户端 - sending video stream from server to client using socket programming in python 使用套接字python从客户端向服务器发送图像 - sending images from client to server using socket python
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM