Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java服务器SSL套接字和Python客户端SSL套接字-服务器发送消息时出现问题_Java_Python_Ssl_Client - Fatal编程技术网

Java服务器SSL套接字和Python客户端SSL套接字-服务器发送消息时出现问题

Java服务器SSL套接字和Python客户端SSL套接字-服务器发送消息时出现问题,java,python,ssl,client,Java,Python,Ssl,Client,我正在尝试与服务器SSL套接字Java和客户端SSL套接字Python通信。发送的第一条消息是正常的,但当服务器发送另一条消息时,客户机将接收分为两部分的消息。例如:如果服务器发送消息“abcdefghij”,则客户端首先接收“a”,然后接收“bcdefghij” 有人知道为什么在第一次收到信息后会分成两部分?问候 客户端代码: import socket, ssl, pprint s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.s

我正在尝试与服务器SSL套接字Java和客户端SSL套接字Python通信。发送的第一条消息是正常的,但当服务器发送另一条消息时,客户机将接收分为两部分的消息。例如:如果服务器发送消息“abcdefghij”,则客户端首先接收“a”,然后接收“bcdefghij”

有人知道为什么在第一次收到信息后会分成两部分?问候

客户端代码:

import socket, ssl, pprint
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
ssl_sock = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1, cert_reqs=ssl.CERT_NONE)
ssl_sock.connect(('localhost', 7000))
pprint.pprint(ssl_sock.getpeercert())

while(1):
    print "Waiting"
    data = ssl_sock.recv()  
    print "Received:", data
    data = ""

ssl_sock.close()
服务器代码:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.security.KeyStore;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;


public class SslReverseEchoer {

    public static void main(String[] args) {
        char ksPass[] = "123456".toCharArray();
        char ctPass[] = "123456".toCharArray();

        try {
            KeyStore ks = KeyStore.getInstance("JKS");
            ks.load(new FileInputStream("keystore.jks"), ksPass);
            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
            kmf.init(ks, ctPass);
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(kmf.getKeyManagers(), null, null);
            SSLServerSocketFactory ssf = sc.getServerSocketFactory();
            SSLServerSocket s = (SSLServerSocket) ssf.createServerSocket(7000);
            printServerSocketInfo(s);
            SSLSocket c = (SSLSocket) s.accept();
            printSocketInfo(c);
            BufferedWriter w = new BufferedWriter(new OutputStreamWriter(c.getOutputStream()));
            BufferedReader r = new BufferedReader(new InputStreamReader(c.getInputStream()));
            //1th time
            String m = "abcdefghj1234567890";
            w.write(m, 0, m.length());
            w.newLine();
            w.flush();
            //2th time
            String m2 = "#abcdefghj1234567890";
            w.write(m2, 0, m2.length());
            w.newLine();
            w.flush();
            //3th time
            String m3 = "?abcdefghj1234567890";
            w.write(m3, 0, m3.length());
            w.newLine();
            w.flush();
            while ((m = r.readLine()) != null) {
                if (m.equals("."))
                    break;
                char[] a = m.toCharArray();
                int n = a.length;
                for (int i = 0; i < n / 2; i++) {
                    char t = a[i];
                    a[i] = a[n - 1 - i];
                    a[n - i - 1] = t;
                }
                w.write(a, 0, n);
                w.newLine();
                w.flush();
            }
            w.close();
            r.close();
            c.close();
            s.close();
        } catch (Exception e) {
            System.err.println(e.toString());
        }
    }

    private static void printSocketInfo(SSLSocket s) {
        System.out.println("Socket class: " + s.getClass());
        System.out.println("   Remote address = " + s.getInetAddress().toString());
        System.out.println("   Remote port = " + s.getPort());
        System.out.println("   Local socket address = " + s.getLocalSocketAddress().toString());
        System.out.println("   Local address = " + s.getLocalAddress().toString());
        System.out.println("   Local port = " + s.getLocalPort());
        System.out.println("   Need client authentication = " + s.getNeedClientAuth());
        SSLSession ss = s.getSession();
        System.out.println("   Cipher suite = " + ss.getCipherSuite());
        System.out.println("   Protocol = " + ss.getProtocol());
    }

    private static void printServerSocketInfo(SSLServerSocket s) {
        System.out.println("Server socket class: " + s.getClass());
        System.out.println("   Socker address = " + s.getInetAddress().toString());
        System.out.println("   Socker port = " + s.getLocalPort());
        System.out.println("   Need client authentication = " + s.getNeedClientAuth());
        System.out.println("   Want client authentication = " + s.getWantClientAuth());
        System.out.println("   Use client mode = " + s.getUseClientMode());
    }
}
导入java.io.BufferedReader;
导入java.io.BufferedWriter;
导入java.io.FileInputStream;
导入java.io.InputStreamReader;
导入java.io.OutputStreamWriter;
导入java.security.KeyStore;
导入javax.net.ssl.KeyManagerFactory;
导入javax.net.ssl.SSLContext;
导入javax.net.ssl.SSLServerSocket;
导入javax.net.ssl.SSLServerSocketFactory;
导入javax.net.ssl.SSLSession;
导入javax.net.ssl.SSLSocket;
公共类SslReverseEchoer{
公共静态void main(字符串[]args){
char ksPass[]=“123456”.toCharArray();
char ctPass[]=“123456”.toCharArray();
试一试{
KeyStore ks=KeyStore.getInstance(“JKS”);
load(新文件输入流(“keystore.jks”),ksPass;
KeyManagerFactory kmf=KeyManagerFactory.getInstance(“SunX509”);
kmf.init(ks,ctPass);
SSLContext sc=SSLContext.getInstance(“TLS”);
sc.init(kmf.getKeyManager(),null,null);
SSLServerSocketFactory ssf=sc.getServerSocketFactory();
sslserversockets=(SSLServerSocket)ssf.createServerSocket(7000);
printServerSocketInfo(s);
SSLSocket c=(SSLSocket)s.accept();
printSocketInfo(c);
BufferedWriter w=新的BufferedWriter(新的OutputStreamWriter(c.getOutputStream());
BufferedReader r=新的BufferedReader(新的InputStreamReader(c.getInputStream());
//第1次
字符串m=“abcdefghj1234567890”;
w、 写入(m,0,m.length());
w、 换行符();
w、 冲洗();
//第二次
字符串m2=“#abcdefghj1234567890”;
w、 写入(m2,0,m2.length());
w、 换行符();
w、 冲洗();
//第三次
字符串m3=“?abcdefghj1234567890”;
w、 写入(m3,0,m3.length());
w、 换行符();
w、 冲洗();
而((m=r.readLine())!=null){
如果(m等于(“.”)
打破
char[]a=m.toCharArray();
int n=a.长度;
对于(int i=0;i
它是服务器端的Naggle算法和客户端TCP堆栈中延迟ACK的组合。您还会发现两个数据包之间有约40ms的延迟

禁用服务器端的Naggle算法以修复:

SSLSocket c = (SSLSocket) s.accept();
c.setTcpNoDelay(true);
有关为什么会出现这种情况的更多信息,请参见:


编辑以添加:注意下面布鲁诺的回答。虽然这描述了您在这里看到的内容的具体原因,但您期望从服务器获得数据的方式并不能保证。

似乎您希望始终能够从另一端读取在一个数据块中发送的任意数量的数据

这是一个常见的错误,并非特定于SSL/TLS,但也与普通TCP通信有关

你应该经常循环阅读你想读的任何东西。您还应该定义协议(或使用现有协议)以考虑命令和请求/响应终止符

例如,HTTP使用空行来通知标题的结尾,使用
内容长度
标题或分块传输编码来通知收件人何时停止阅读正文


SMTP使用行分隔命令和单个
作为邮件的结尾。

我尝试用两种方法解决问题,邮件总是在第一个字符处中断,因此我决定在每条邮件的开头和结尾处添加三个空格。因此,当客户机收到它们时,对消息进行修剪。 我发现的另一种方法是使用DataOutputStream,一种逐字节传递writeBytes的方法,在服务器和cli上使用它