Java SSL 套接字通信 - 发送和接收
Java SSL Socket Communication - Both Sending and Receiving
考虑客户端向服务器发送消息,然后服务器回复客户端。
客户代码
public void run() {
try {
SSLSocketfactory f = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket socket = (SSLSocket) f.createSocket(Common.JSON_SERVER_IP, Integer.parseInt(Common.JSON_SERVER_PORT));
String[] suites = socket.getSupportedCipherSuites();
socket.setEnabledCipherSuites(suites);
Log.i("Socket", "Created");
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
File f = new File(Common.PATH, Common.JSON_FILE_NAME);
FileInputStream fis = new FileInputStream(f);
byte sendBytes[] = new byte[1024];
int fileSize = 0;
int length = 0;
// Data Send Start!
while ((length = fis.read(sendBytes, 0, sendBytes.length)) > 0) {
fileSize += length;
dos.write(sendBytes, 0, length);
dos.flush();
}
Log.i("Socket", "Data Send Finish");
final int final_fileSize = fileSize;
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(activity.getApplicationContext(), "JSON File Size :" + final_fileSize + "Bytes", Toast.LENGTH_SHORT).show();
}
});
Log.i("Socket", "Output Close");
// Data Receive Start!
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
// receive the response from Server
String reply = "";
String str = "JSON";
Log.i("Socket", "Receive Ready");
/* Example result from Server
{
"ret":[{"id":"COM_DATA_002","errCd":0, "errMsg":""}],
"Value":[{"updateType":0, "fileURL":"http://127.0.0.1/filePath"}]
}*/
while ((reply = br.readLine()) != null) {
Log.i("Socket", "Parsing");
Object obj_p=JSONValue.parse(reply);
JSONObject obj_j=(JSONObject)obj_p;
Object target = obj_j.get("Value");
JSONArray obj_value = (JSONArray)target;
JSONObject url_val=(JSONObject)obj_value.get(0);
String url = (String)url_val.get("fileURL");
URL urlDB = new URL(url);
URLConnection getDB = urlDB.openConnection();
// Get New DB or query
}
Log.i("Socket", "File Get");
if(str.length() != 0) {
str = "[" + Common.getDateCurrentTimeZone(System.currentTimeMillis()) + "]\n" + str + "\n";
Log.i(Common.TAG, str);
}
final String text = str;
is.close();
br.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (dos != null)
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
if (fis != null)
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
if (socket != null)
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
服务器代码
public void run() {
String fileName = "JSON.txt";
try {
// receive file
receiveFile(fileName);
// load receive file
File file = new File(Common.defaultReceivedData, fileName);
BufferedReader in = new BufferedReader(new FileReader(file));
// String SendfileName = "ClientVersion.txt";
String SendfileName = "Return.txt";
File SendFile = new File(Common.defaultSendData, SendfileName);
String s;
Object obj;
JSONObject obj2;
String det;
// File write and send...
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void receiveFile(String fileName) throws IOException{
int length = 0;
int size = 0;
DataInputStream dis = new DataInputStream(send.getInputStream());
fileName = "JSON.txt";
FileOutputStream fos = new FileOutputStream(new File(Common.defaultReceivedData, fileName));
byte[] inputByte = new byte[1024];
while ((length = dis.read(inputByte, 0, inputByte.length)) > 0) {
System.out.println(length);
size += length;
fos.write(inputByte, 0, length);
fos.flush();
}
fos.close();
System.out.println("Received JSON data! [FileSize: " + size + "]");
}
当客户端向服务器端发送消息时,通信卡住了。
客户
03-11 15:38:46.476: I/Socket(30160): Created
03-11 15:38:46.606: I/Socket(30160): Data Send Finish
03-11 15:38:46.606: I/Socket(30160): Output Close
03-11 15:38:46.616: I/Socket(30160): Receive Ready
服务器
Client is connected: IP is xxx.xxx.xxx.xxx
57
在这段代码中,服务器只有在客户端停止后才完成接收消息。
怎样才能正常完成这次通信呢?
服务器正在从套接字读取文件,直到流结束。
客户端不会关闭连接,而是会再次尝试从服务器读取响应,直到流结束。
所以两个对等方都没有关闭连接,所以流的结尾永远不会到达,所以双方都在读取中被阻塞,所以你已经实现了网络死锁。
你需要在文件前发送文件长度,让服务器知道什么时候停止读取。
或者,如果你只打算为每个连接发送一个文件,客户端可以关闭输出连接,这会给服务器它正在寻找的 EOS,于是它的读取循环会终止,它会发送它的回复,然后关闭连接,这会给客户端 it 正在寻找的 EOS因为,所以它会脱离它的读取循环并关闭连接。
考虑客户端向服务器发送消息,然后服务器回复客户端。
客户代码
public void run() {
try {
SSLSocketfactory f = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket socket = (SSLSocket) f.createSocket(Common.JSON_SERVER_IP, Integer.parseInt(Common.JSON_SERVER_PORT));
String[] suites = socket.getSupportedCipherSuites();
socket.setEnabledCipherSuites(suites);
Log.i("Socket", "Created");
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
File f = new File(Common.PATH, Common.JSON_FILE_NAME);
FileInputStream fis = new FileInputStream(f);
byte sendBytes[] = new byte[1024];
int fileSize = 0;
int length = 0;
// Data Send Start!
while ((length = fis.read(sendBytes, 0, sendBytes.length)) > 0) {
fileSize += length;
dos.write(sendBytes, 0, length);
dos.flush();
}
Log.i("Socket", "Data Send Finish");
final int final_fileSize = fileSize;
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(activity.getApplicationContext(), "JSON File Size :" + final_fileSize + "Bytes", Toast.LENGTH_SHORT).show();
}
});
Log.i("Socket", "Output Close");
// Data Receive Start!
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
// receive the response from Server
String reply = "";
String str = "JSON";
Log.i("Socket", "Receive Ready");
/* Example result from Server
{
"ret":[{"id":"COM_DATA_002","errCd":0, "errMsg":""}],
"Value":[{"updateType":0, "fileURL":"http://127.0.0.1/filePath"}]
}*/
while ((reply = br.readLine()) != null) {
Log.i("Socket", "Parsing");
Object obj_p=JSONValue.parse(reply);
JSONObject obj_j=(JSONObject)obj_p;
Object target = obj_j.get("Value");
JSONArray obj_value = (JSONArray)target;
JSONObject url_val=(JSONObject)obj_value.get(0);
String url = (String)url_val.get("fileURL");
URL urlDB = new URL(url);
URLConnection getDB = urlDB.openConnection();
// Get New DB or query
}
Log.i("Socket", "File Get");
if(str.length() != 0) {
str = "[" + Common.getDateCurrentTimeZone(System.currentTimeMillis()) + "]\n" + str + "\n";
Log.i(Common.TAG, str);
}
final String text = str;
is.close();
br.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (dos != null)
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
if (fis != null)
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
if (socket != null)
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
服务器代码
public void run() {
String fileName = "JSON.txt";
try {
// receive file
receiveFile(fileName);
// load receive file
File file = new File(Common.defaultReceivedData, fileName);
BufferedReader in = new BufferedReader(new FileReader(file));
// String SendfileName = "ClientVersion.txt";
String SendfileName = "Return.txt";
File SendFile = new File(Common.defaultSendData, SendfileName);
String s;
Object obj;
JSONObject obj2;
String det;
// File write and send...
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void receiveFile(String fileName) throws IOException{
int length = 0;
int size = 0;
DataInputStream dis = new DataInputStream(send.getInputStream());
fileName = "JSON.txt";
FileOutputStream fos = new FileOutputStream(new File(Common.defaultReceivedData, fileName));
byte[] inputByte = new byte[1024];
while ((length = dis.read(inputByte, 0, inputByte.length)) > 0) {
System.out.println(length);
size += length;
fos.write(inputByte, 0, length);
fos.flush();
}
fos.close();
System.out.println("Received JSON data! [FileSize: " + size + "]");
}
当客户端向服务器端发送消息时,通信卡住了。
客户
03-11 15:38:46.476: I/Socket(30160): Created
03-11 15:38:46.606: I/Socket(30160): Data Send Finish
03-11 15:38:46.606: I/Socket(30160): Output Close
03-11 15:38:46.616: I/Socket(30160): Receive Ready
服务器
Client is connected: IP is xxx.xxx.xxx.xxx
57
在这段代码中,服务器只有在客户端停止后才完成接收消息。 怎样才能正常完成这次通信呢?
服务器正在从套接字读取文件,直到流结束。
客户端不会关闭连接,而是会再次尝试从服务器读取响应,直到流结束。
所以两个对等方都没有关闭连接,所以流的结尾永远不会到达,所以双方都在读取中被阻塞,所以你已经实现了网络死锁。
你需要在文件前发送文件长度,让服务器知道什么时候停止读取。
或者,如果你只打算为每个连接发送一个文件,客户端可以关闭输出连接,这会给服务器它正在寻找的 EOS,于是它的读取循环会终止,它会发送它的回复,然后关闭连接,这会给客户端 it 正在寻找的 EOS因为,所以它会脱离它的读取循环并关闭连接。