Secure Sockets Layer Java Network Programming Secure Network Communication

SSL (Secure Socket Layer, Secure Socket Layer) is a protocol that ensures secure communication between two nodes on the network. The IETF (Interet Engineering Task Force) international organization standardized SSL, developed the RFC2246 specification, and called it Transport Layer Security (TLS)

Both SSL and TLS are based on TCP/IP, and some application layer protocols, such as HTTP and IMAP, can use SSL to ensure secure communication. HTTP built on the SSL protocol is called the HTTPS protocol. The default port used by HTTP is 80 and the default port used by HTTPS is 443

SSL uses encryption technology to achieve secure communication, to ensure the confidentiality and integrity of communication data, and to ensure that both parties in communication can verify the identity of each other

1. Encrypted communication

When the client communicates with the server, the communication data may be illegally monitored by other computers on the network. SSL uses encryption technology to realize the safe transmission of information between the two parties in the session. The basic principle of encryption technology is that when data is sent from one end to another, the sender first encrypts the data and then sends it to the receiver. In this way, encrypted data is transmitted over the network. If someone illegally intercepts this batch of data on the network, since there is no decryption key, it is impossible to obtain the real original data. After receiving the encrypted data, the receiver first decrypts the data, and then processes

2. Security certificate

In addition to encrypting data communication, SSL also uses an identity authentication mechanism to ensure that both parties in the communication can verify the true identity of the other party. This is very similar to how we use ID cards to prove our identity in life. For example, when you go to the bank to withdraw money and you claim to be Zhang San, how can you convince the other party of your identity? The most effective way is to show ID. Everyone has a unique ID card, which records your real information. Identity cards are issued by state authorities and forgery is not allowed. On the premise that the ID card cannot be faked and copied by others, as long as you show your ID card, you can prove your identity

Individuals can prove their identity through their ID card, and for a unit, such as a shopping mall, they can prove their identity through a business license. The business license is also issued by the national authority and forgery is not allowed, which guarantees the credibility of the business license

SSL uses a security certificate to prove the identity of the client or server. When the client communicates with the server through a secure connection, the server will first present its security certificate to the client. This certificate declares that the server is safe, and it is indeed the server. A certificate is unique all over the world, and other illegal servers cannot fake it. A security certificate can be compared to an electronic ID card

For a single customer, it is troublesome to go to a recognized authority to obtain a security certificate. In order to expand the customer base and facilitate customer access, many servers do not require customers to present security certificates. In some cases, the server will also ask the client to present a security certificate in order to verify the client's identity, mainly in B2B transactions

There are two ways to obtain a security certificate, one is to obtain a certificate from an authority, and the other is to create a self-signed certificate

2.1 Obtain a certificate from an authority

The security certificate is issued by an internationally authoritative certificate authority, which guarantees the credibility of the certificate. When applying for a security certificate, a certain fee must be paid. A security certificate is only valid for one IP address. If there are multiple IP addresses in the user's system environment, a security certificate must be purchased for each IP address.

2.2 Create a self-signed certificate

In some occasions, both communicating parties only care about the secure transmission of data on the network, and do not require the other party to perform identity verification. In this case, a self-signed certificate can be created. Just like the business cards made by users themselves, they lack authority and fail to achieve the purpose of identity authentication. When you hand over your business card to the other party, the business card claims that you are the boss of a large company. Believe it or not can only be judged by the other party.

Since self-signed certificates don't effectively prove your identity, what's the point? Technically, whether it is a certificate obtained from an authority or a certificate made by oneself, the encryption technology used is the same. Using these certificates, secure encrypted communication can be realized

3. SSL handshake

A security certificate contains both the key used to encrypt data and the digital signature used to verify identity. The security certificate adopts public key encryption technology, and public key encryption refers to the use of a pair of asymmetric keys for encryption or decryption. Each pair of keys consists of a public key and a private key. The public key is widely distributed, and the private key is hidden and not disclosed. Data encrypted with the public key can only be decrypted with the private key, and conversely, data encrypted with the private key can only be decrypted with the public key

When the client communicates with the server, an SSL handshake must be performed first. The SSL handshake mainly completes the following tasks:

  • The cipher suite used for negotiation, which includes a set of encryption parameters, which specify information such as the encryption algorithm and the length of the key
  • Verify the identity of the other party, this operation is optional
  • Determine the encryption algorithm used

The SSL handshake process uses asymmetric encryption to transfer data, thereby establishing a secure session. After the SSL handshake is completed, the communication parties will use the symmetric encryption method to transmit the actual application data. The so-called symmetric encryption means that both parties in communication use the same key to encrypt data

The specific process of SSL handshake is as follows:

  1. The client sends its own SSL version number, encryption parameters, session-related data, and other necessary information to the server
  2. The server sends its own SSL version number, encryption parameters, session-related data, and other necessary information to the client, as well as the server's certificate. If the server needs to verify the identity of the client, the server will also issue a request for the client to provide a security certificate
  3. The client verifies the server certificate, and if the verification fails, it prompts that the SSL connection cannot be established. If successful, proceed to the next step
  4. The client generates a pre-master secret for this session, encrypts it with the public key attached to the server security certificate, and sends it to the server
  5. If the server asks to verify the identity of the client, the client needs to sign some other data and send it to the server together with the client certificate
  6. If the server requires authentication of the client, it checks that the CA that signed the client's certificate is trusted. If not in the trusted list, end the session. If the check is passed, the server decrypts the received preliminary master password with its own private key, and uses it to generate the master password (master secret) of this session through some algorithms
  7. Both the client and the server use this master password to generate a session key (symmetric key) for this session. Any messages passed after the end of the two-way SSL handshake use this session key. The main reason for this is that the calculation volume of symmetric encryption is more than an order of magnitude lower than that of asymmetric encryption, which can significantly improve the calculation speed of the conversation between the two parties.
  8. The client notifies the server that all messages sent thereafter will be encrypted using this session key, and notifies the server that the client has completed the SSL handshake
  9. The server notifies the client that all subsequent messages will be encrypted using this session key, and the server has completed the SSL handshake
  10. The handshake process is over and the session has been established. During the next session, both parties use the same session key to encrypt and decrypt the sent and received information respectively

4. Create a self-signed security certificate

JDK provides a tool keytool for making certificates, its location is: <JDK root directory>\bin\keytool.exe

The keytool tool proposes the concept of a keystore, which can contain multiple entries, each entry includes a self-signed security certificate and a pair of asymmetric keys

The command to create a keystore through the keytool tool is:

 
 

keytool -genkeypair -alias weiqin -keyalg RSA -keystore C:\chapter15\test.keystore

  • genkeypair: Generate a pair of asymmetric keys
  • alias: Specifies the alias of the entry and key pair, which is public
  • keyalg: Specify the encryption algorithm, in this example, the general RSA algorithm is used
  • keystore: Set the storage path and file name of the keystore file

During the running process of the command, you will first be prompted to enter the password of the keystore, and then prompted to enter personal information, such as name, organizational unit, and city, etc., as long as you enter the real information

The following command checks the information of the test.keystore secret library, and the information of the entries contained in it will be listed

 
 

keytool -list -v -keystore C:\chapter15\test.keystore -storepass "123456”

The following command exports the entry with the alias of weiqin in the test.keystore keystore to a security certificate with the file name of weiqin.crt. The weiqin.crt file contains the self-signed security certificate and the public key in the key pair, but does not contain the private key in the key pair

 
 

keytool -export -alias weigin -keystore C:\chapter15\test.keystore -file C:\chapter15\weigin.crt -storepass “123456”

The following command deletes the entry with the alias weiqin in the test.keystore keystore

 
 

keytool -delete -alias weigin -keystore C:\chapter15\test.keystore -storepass “123456”

The following command imports the weiqin.crt security certificate into the testTrust.keystore keystore to generate an entry with the alias weiqin, which contains the public key in the key pair, but does not contain the private key in the key pair

 
 

keytool -import -alias weiqin -keystore C:\chapter15\testTrust.keystore -file C:\chapter15\weiqin.crt -storepass "123456"

2 | 0 Introduction to JSSE

JSSE encapsulates the underlying complex security communication details, making it easy for developers to use it to develop secure network applications

1. KeyStore, KeyManager and TrustManager classes

When performing secure communication, both the client and the server are required to support the SSL or TCL protocol. Both the client and the server may need to set security certificates used to verify their identities, and which security certificates of the other party to trust. More commonly, the server only needs to set the security certificate used to prove its identity, and the client only needs to set which security certificates of the server to trust

The KeyStore class is used to store the keystore containing the security certificate. The following program code creates a KeyStore object, which loads the security certificate from the test.keystore keystore file

 
 

String passphrase = "123456"; //JKS is the type of KeyStore supported by JDK KeyStore keyStore = KeyStore.getInstance("JKS"); char[] password = passphrase.toCharArray(); //password parameter is used to open the keystore keyStore.load(new FileInputStream("test.keystore"), password);

The task of the KeyManager interface is to select the security certificate used to prove its identity and send it to the other party. KeyManagerFactory is responsible for creating KeyManager objects, e.g.

 
 

KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509"); keyManagerFactory.init(keyStore, password); KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();

The task of the TrustManager interface is to decide whether to trust the other party's security certificate. TruesManagerFactory is responsible for creating TrustManager objects, e.g.

 
 

TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509"); trustManagerFactory.init (keyStore); TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();

2. SSLContext class

The SSLContext class is responsible for setting various information related to secure communication, such as the protocol used (SSL or TLS), its own security certificate and the other party's security certificate. SSLContext is also responsible for constructing SSLServerSocketFactory, SSLSocketFactory and SSLEngine objects

The following program code creates and initializes an SSLContext object, which then creates an SSLServerSocketFactory object

 
 

SSLContext sslCtx = SSLContext.getInstance("TLS");//采用TLS协议 sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); SSLServerSocketFactory ssf = sslCtx.getServerSocketFactory();

The init method of SSLContext is defined as follows

 
 

public final void init(KeyManager[] km, TrustManager[] tm, SecureRandom random) throws KeyManagementException

  • The parameter random is used to set the secure random number, if the parameter is null, the init method will use the default SecureRandom implementation
  • If the parameter km is null, the init method will create the default KeyManager object and its associated KeyStore object, and the KeyStore object will get the security certificate from the system property javax.net.ssl.keyStore. If no such system property exists, the KeyStore object content is empty
  • If the parameter tm is null, the init method will create a default TrustManager object and its associated KeyStore object. The KeyStore object obtains the security certificate according to the following steps:
    • First try to get the security certificate from the system property javax.net.ssl.trustStore
    • If the previous step fails, use the <JDK root directory>/lib/security/jssecacerts file as the security certificate
    • If the previous step fails, use the <JDK root directory>/lib/security/cacerts file as the security certificate
    • If the previous step failed, the contents of the KeyStore object is empty

3. SSLServerSocketFactory class

The SSLServerSocketFactory class is responsible for creating SSLServerSocket objects

 
 

SSLServerSocket serverSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(8000); // Listen on port 8000

SSLServerSocketFactory objects have two creation methods:

  • Call the getServerSocketFactory method of the SSLContext class
  • Call the static getDefault method of the SSLServerSocketFactory class

The static getDefault method of the SSLServerSocketFactory class returns a default SSLServerSocketFactory object, which is associated with a default SSLContext object, and the implementation of the getDefault method initializes the default SSLContext object as follows

 
 

sslContext.init(null,null,null);

4. SSLSocketFactory class

The SSLSocketFactory class is responsible for creating SSLSocket objects

 
 

SSLSocket socket = (SSLSocket) sslSocketFactory.createSocket("localhost",8000);

SSLSocketFactory objects have two creation methods

  • Call the getSocketFactory method of the SSLContext class
  • Call the static getDefault method of the SSLSocketFactory class

The static getDefault method of the SSLSocketFactory class returns a default SSLSocketFactory object, which is associated with a default SSLContext object. The implementation of the getDefault method initializes the default SSLContext object as follows

 
 

sslContext.init(null,null,null);

5. SSLSocket class

The SSLSocket class is a subclass of the Socket class, so there are many similarities in usage. In addition, the SSLSocket class has methods related to secure communication

5.1 Set Cipher Suite

The client and the server need to negotiate the actual cipher suite used during the handshake phase. The following two situations will cause the handshake to fail:

  • There is no identical cipher suite that both parties can use
  • Despite the presence of such a cipher suite, one or both parties do not have a security certificate to use the cipher suite

The getSupportedCipherSuites method of the SSLSocket class returns a string array containing the CipherSuites supported by the SSLSocket object. The setEnabledCipherSuites(String[] suites) method of the SSLSocket class sets the available cipher suites for the current SSLSocket object, and the available cipher suites should be a subset of the supported cipher suites

The following code only enables cipher suites with high encryption strength, which can improve the security of the communication terminal, and prohibit those communication terminals that do not support strong encryption from connecting to the current communication terminal

 
 

String[] strongSuites = { "SSL_RSA_WITH_RC4_128_MD5", "SSL_RSA_WITH_RC4_128_SHA", "SSL_RSA_WITH_3DES_EDE_CBC_SHA" }; sslSocket.setEnabledCipherSuites(strongSuites);

5.2 Handling the handshake end event

The SSL handshake takes a long time. When the SSL handshake is completed, a HandshakeCompletedEvent event will be sent, which is monitored by HandshakeCompletedListener. The addHandshakeCompletedListener method of the SSLSocket class is responsible for registering the HandshakeCompletedListener listener

The following example registers HandshakeCompletedListener for SSLSocket

 
 

socket.addHandshakeCompletedListener { new HandshakeCompletedListener() { public void handshakeCompleted(HandshakeCompletedEvent event) { System.out.println("Handshake completed"); System.out.println("The cipher suite is:" + event.getCipherSuite()); System .out.println("The session is:" + event.getSession()); System.out.println("The communication partner is:" + event.getSession().getPeerHost()); } }); }

5.3 Managing SSL sessions

A client program may open multiple secure sockets to the same port on a server. If the SSL handshake is performed for each secure connection, the communication efficiency will be greatly reduced. In order to improve the efficiency of secure communication, the SSL protocol allows multiple SSLSockets to share the same SSL session. In the same session, only the first opened SSLSocket needs to perform SSL handshake, which is responsible for generating keys and exchanging keys, and the rest of SSLSockets share key information. JSSE automatically reuses sessions if a client program opens multiple secure sockets to the same port on a server within a reasonable time frame

The getSession method of SSLSocket returns the session to which the SSLSocket belongs. SSLSocket's setEnableSessionCreation(boolean flag) method determines whether SSLSocket allows new sessions to be created. The default value of flag is true. If the flag parameter is true, then for the newly created SSLSocket, if there is an available session, it will directly join the session, if there is no available session, a new session will be created. If flag is a false parameter, then for the newly created SSLSocket, if there is an available session, it will directly join the session, if there is no available session, then the SSLSocket cannot communicate securely with the other party

The startHandshake method of SSLSocket explicitly performs an SSL handshake, which has the following purposes:

  • make the session use the new key
  • make the session use the new cipher suite
  • Restart a session. In order to ensure that the original session is not reused, the original session should be invalidated first,,
 
 

socket.getSession().invalidate(); socket.startHandshake();

5.4 Client mode

In most cases, the client does not need to prove its identity to the server, so when a communication end does not need to prove its identity to the other party, it is said to be in client mode, otherwise it is said to be in server mode. Only one of the communication parties can be in server mode, and the other can be in client mode

The setUseClientMode(boolean mode) method of SSLSocket is used to set the client mode or server mode. If the mode parameter is true, it means that it is in the client mode, that is, there is no need to prove its identity to the other party; if the mode is false, it means that it is in the server mode, that is, it needs to prove its worth to the other party

When the SSL initial handshake has started, it is not allowed to call the seUseClientMode(boolean mode) method of SSLSocket, otherwise it will cause an exception

When SSLSocket is in server mode, the following methods can also be used to determine whether to require the other party to provide identity authentication:

  • setWantClientAuth(boolean want):: When the want parameter is true, it means that the other party is expected to provide identity authentication. If the other party does not present the security certificate, the connection will not be interrupted, and the communication can continue.
    setNeedClientAuth(boolean need): When the need parameter is true, it means that the other party must provide identity authentication. If the other party does not present a security certificate, the connection is broken and communication cannot continue

6. SSLServerSocket class

The SSLServerSocket class is a subclass of the ServerSocket class, so there are many similarities in usage. In addition, the SSLServerSocket class has methods related to secure communication that have the same effect as the methods of the same name in the SSLSocket class

7. SSLEngine class

The combination of SSLEngine class and SocketChannel class can realize non-blocking secure communication. The SSLEngine class encapsulates the details related to secure communication, and packs the application data sent by the application program into network data. Packing refers to encrypting the application data, adding SSL handshake data, and turning it into network data. The SSLEngine class can also expand the received network data into application data, which refers to decrypting the network data and removing the SSL handshake data in it, so as to restore the application data that can be processed by the application. The wrap method of the SSLEngine class is responsible for packaging application data, and the unwrap method is responsible for expanding network data

 
 

public class SSLEngineDemo { private static boolean logging = true; private SSLContext sslc; private SSLEngine clientEngine; //client Engine private ByteBuffer clientOut; //store the application data sent by the client private ByteBuffer clientIn; //store the application received by the client Data private SSLEngine serverEngine; //Server-side Engine private ByteBuffer serverOut; //store application data sent by server-side private ByteBuffer serverIn; //store application data received by server-side private ByteBuffer cTOs;//store client-side send to server-side private ByteBuffer sTOc;//store the network data sent by the server to the client//set the keystore file, truststore file and password private static String keyStoreFile = "test.keystore"; private static String trustStorefile = "test. keystore"; private static String passphrase = "123456"; public static void main(String args[]) throws Exception { SSLEngineDemo demo = new SSLEngineDemo(); demo.runDemo(); } /**Initialize SSLContext*/ public SSLEngineDemo( ) throws Exception { KeyStore ks = KeyStore.getInstance("JKS"); KeyStore ts = KeyStore.getInstance("JKS"); char[] password = passphrase.toCharArray(); ks.load(new FileInputStream(keyStoreFile), password); ts.load(new FileInputStream(trustStoreFile), password); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(ks, password); TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); tmf.init(ts); SSLContext sslCtx = SSLContext.getInstance("TLS"); sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); sslc = sslCtx; } private void runDemo() throws Exception { boolean dataDone = false; /*创建客户端以及服务器端的SSLEngine*/ serverEngine = sslc.createSSLEnqine(); serverEngine.setUseClientMode(false); serverEngine.setNeedClientAuth(true); clientEngine = sslc.createSSLEngine("client", 80); clientEngine.setUseClientMode(true); /* Create client and server application buffers and network buffers*/ SSLSession session = clientEngine.getsSession(); int appBufferMax = session.getApplicationBufferSize(); int netBufferMax = session.getPacketBufferSize(); clientIn = ByteBuffer.allocate(appBufferMax + 50); serverIn = ByteBuffer.allocate(appBufferMax + 50) cTOs = ByteBuffer.allocateDirect(netBufferMax); sTOc = ByteBuffer.allocateDirect(netBufferMax); clientOut = ByteBuffer.wrap("Hi Server, I' m Client".getBytes()); serverOut = ByteBuffer.wrap("Hello Client, I'm Server".getBytes()); SSLEngineResult clientResult; SSLEngineResult serverResult; while (!isEnqineClosed(clientEngine) || !isEngineClosed(serverEngine) ) { log("=================="); // client packaging application data clientResult = clientEngine.wrap(clientOut, cTOs); log("client wrap: ",clientResult); //Complete handshake task runDelegatedTasks(clientResult, clientEngine); //Server-side packaged application data serverResult = serverEngine.wrap(serverOut, sTOc); log("server wrap:", serverResult); //Complete handshake task runDelegatedTasks (serverResult, serverEngine); cTOs.flip(); sTOc.flip(); log("---------------"); //The client expands the network data clientResult = clientEngine. unwrap(sTOc, clientIn); log("client unwrap:", clientResult); //Complete the handshake task runDelegatedTasks(clientResult, clientEngine); //Expand the network data on the server serverResult = serverEngine.unwrap(cTOs, serverIn); log( "server unwrap:", serverResult); //Complete the handshake task runDeleqatedTasks(serverResult, serverEngine); cTOs.compact(); sTOc.compact(); if (!dataDone && (clientOut.limit() == serverIn.position( )) && (serverOut, limit()=m clientIn. position())) { checkTransfer(serverOut, clientIn); checkTransfer(clientOut,serverIn); log("\tClosing clientEngine's *OUTBOUND*..."); clientEngine.closeOutbound(); dataDone = true; } } } /**当SSLEngine的输出与输入都关闭时,意味着SSLEngine被关闭*/ private static boolean isEngineClosed(SSLEngine engine) { return(engine.isOutboundDone() && engine.isInboundDone()); } /**执行SSL握手任务*/ private static void runDelegatedTasks(SSLEngineResult result, SSLEngine engine) throws Exception { if(result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { Runnable runnable; while((runnable = engine.getDelegatedTask()) != null) { log("\trunning delegated task..."); runnable.run(); } HandshakeStatus hsStatus = engine.getHandshakeStatus(); if(hsStatus == HandshakeStatus.NEED_TASK) { throw new Exception("handshake shouldn't need additional tasks"); } log("\tnew HandshakeStatus:" + hsStatus); } } /**判断两个缓冲区内容是否相同*/ private static void checkTransfer(ByteBuffer a, ByteBuffer b) throws Exception { a.flip(); b.flip(); if(!a.equals(b)) { throw new Exception("pata didn't transfer cleanly"); } else { log("\tData transferred cleanly"); } a.position(a.limit()); b.position(b.limit()); a.limit(a.capacity()); b.limit(b.capacity()); } private static boolean resultOnce = true; /**输出日志,打印SSLEngineResult的结果*/ private static void log(String str, SSLEngineResult result) { if(resultOnce) { resultOnce = false; System.out.println("The format of the SSLEngineResult is: \n" +"\t\"getStatus() / getHandshakeStatus()\”+\n" +"\t\"bytesConsumed() / bytesProduced()\"\n"); } HandshakeStatus hsStatus = result.getHandshakeStatus(); log(str + result,getStatus() + "/" + hsStatus + "," + result,bytesConsumed() + "/" + result.bytesProduced() + " bytes"); if (hsStatus == HandshakeStatus.FINISHED) { log("\t...ready for application data"); } } /**输出日志*/ private static void log(String str) { System.out.printin(str); } }

3 | 0 Create SSL-based secure servers and secure clients

 
 

public class EchoServer { private int port = 8000; private SSLServerSocket serverSocket; public EchoServer() throws Exception { // output trace log SSLContext context = createSSLContext(); SSLServerSocketFactory factory = context.getServerSocketFactory(); serverSocket = (SSLServerSocket) factory. createServerSocket (poxt); String[] supported = serverSocket.getSupportedCipherSuites(); serverSocket.setEnabledCipherSuites(supported); } public SSLContext createSSLContext() throws Exception { //The key store where the security certificate used by the server to verify its identity is located String keyStoreFile = "test.keystore"; String passphrase = "123456"; KeyStore ks = KeyStore.getInstance("JKS"); char[] password = passphrase.toCharArray(); ks.load(new FileInputStream(keyStoreFile), password); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(ks,password); SSLContext sslContext = SSLContext.getInstance("SSL"); sslContext.init(kmf.getKeyManagers(), null, null); //When the client is required to provide a security certificate, the server can create a TrustManagerFactory, //and TrustManager is created by it, and TrustManger decides whether to trust the security certificate provided by the client based on the information in the KeyStore associated with it //The keystore where the security certificate that the client uses to verify its identity is located //String trustStorefile = "test. keystore"; //KeyStore ts = KeyStore.getInstance("JKS"); //ts.load(new FileInputStream(trustStoreFile), password); //TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); //tmf. init(ts); //sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); return sslContext; } private PrintWriter getWriter(Socket socket) throws IOException { OutputStream socketOut = socket.getOutputStream(); return new PrintWriter(socketOut,true); } private BufferedReader getReader(Socket socket) throws IOException { InputStream socketIn = socket.getInputstream(); return new BufferedReader(new InputStreamReader(socketIn)); } public void service() { while (true) { Socket socket = null; try { //等特客户连接 socket = serverSocket.accept(); BufferedReader br = getReader(socket); PrintWriter pw = getWriter(socket); String msg = null; while ((msg = br.readLine()) != null) { System.out.println(msg); if (msg.equals("bye")) { break; } } } catch (IOException e) { e.printStackTrace(); } finally { try { if(socket != null) socket.close(); //断开连接 } catch (IOException e) { e.printStackTrace(); } } } } public static void main(String args[]) throws Exception { new EchoServer().service(); } }getInputstream(); return new BufferedReader(new InputStreamReader(socketIn)); } public void service() { while (true) { Socket socket = null; try { //等特客户连接 socket = serverSocket.accept(); BufferedReader br = getReader(socket); PrintWriter pw = getWriter(socket); String msg = null; while ((msg = br.readLine()) != null) { System.out.println(msg); if (msg.equals("bye")) { break; } } } catch (IOException e) { e.printStackTrace(); } finally { try { if(socket != null) socket.close(); //断开连接 } catch (IOException e) { e.printStackTrace(); } } } } public static void main(String args[]) throws Exception { new EchoServer().service(); } }getInputstream(); return new BufferedReader(new InputStreamReader(socketIn)); } public void service() { while (true) { Socket socket = null; try { //等特客户连接 socket = serverSocket.accept(); BufferedReader br = getReader(socket); PrintWriter pw = getWriter(socket); String msg = null; while ((msg = br.readLine()) != null) { System.out.println(msg); if (msg.equals("bye")) { break; } } } catch (IOException e) { e.printStackTrace(); } finally { try { if(socket != null) socket.close(); //断开连接 } catch (IOException e) { e.printStackTrace(); } } } } public static void main(String args[]) throws Exception { new EchoServer().service(); } }readLine()) != null) { System.out.println(msg); if (msg.equals("bye")) { break; } } } catch (IOException e) { e.printStackTrace(); } finally { try { if(socket != null) socket.close(); //断开连接 } catch (IOException e) { e.printStackTrace(); } } } } public static void main(String args[]) throws Exception { new EchoServer().service(); } }readLine()) != null) { System.out.println(msg); if (msg.equals("bye")) { break; } } } catch (IOException e) { e.printStackTrace(); } finally { try { if(socket != null) socket.close(); //断开连接 } catch (IOException e) { e.printStackTrace(); } } } } public static void main(String args[]) throws Exception { new EchoServer().service(); } }

 
 

public class EchoClient { private String host = "localhost"; private int port = 8000; private SSLSocket socket; public EchoClient() throws IOException { SSLContext context = createSSLContext(); SSLSocketFactory factory = context.getSocketFactory(); socket = (SSLSocket)factory.createSocket(host,port); Stringl] supported = socket.getSupportedCipherSuites(); socket.setEnabledCipherSuites(supported); } public SSLContext createSSLContext() throws Exception { String passphrase = "123456"; char[] password = passphrase.toCharArray(); //设置客户端所信任的安全证书所在的密钥库 String trustStoreFile = "test.keystore"; KeyStore ts = KeyStore.getInstance("JKS"); ts.load(new FileInputStream(trustStoreFile), password)); TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); tmf.init(ts); SSLContext sslContext = SSLContext.getInstance("SSL"); sslContext.init(null, tmf.getTrustManagers(), null); return sslContext; } public static void main(String args[]) throws IOException { new EchoClient().talk(); } public void talk()throws IOException { try { BufferedReader br = getReader(socket); PrintWriter pw = getWriter(socket); BufferedReader localReader = new BufferedReader(new InputStreamReader(System.in)); String msg = null; while((msg = localReader.readLine()) != null) { pw.println(msg); System.out.println(br.readline()); if(msg.equals("bye")) { break; } } } catch(IOException e) { e.printStackTrace(); } finally { try { if(socket != null) socket.close(); //断开连接 } catch (IOException e) { e.printStackTrace(); } } } private PrintWriter getWriter(Socket socket) throws IOException { OutputStream socketOut = socket.getoutputstream(); return new PrintWriter(socketOut, true); } private BufferedReader getReader(Socket socket) throws IOException { InputStream socketIn = socket.getInputstream(); return new BufferedReader(new InputStreamReader(socketIn)); } }

Guess you like

Origin blog.csdn.net/yetaodiao/article/details/131415699