我正在开发一个 Android 应用程序(客户端)并希望它使用 TCP 通信与我的 Java 服务器连接,到目前为止一切顺利。
服务器代码:
import java.net.*;
import java.io.*;
import globalvariables.GlobalVariables;
import interface_package.ServerInterface;
import java.util.Timer;
/**
*
* @author wsserver
*/
public class ThreadedAndroidServer {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
GlobalVariables.init();
//Prevzemi staticen interface
GlobalVariables.sinterface = new ServerInterface();
GlobalVariables.sinterface.show();
//INFINITE LOOP
while(true)
int port = GlobalVariables.portNo;
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(port);
System.out.println("Server has started listening on port " + port);
GlobalVariables.sinterface.setServerStatus("Server has started listening on port " + port);
} catch (IOException e) {
System.out.println("Error: Cannot listen on port " + port + " : " + e);
GlobalVariables.sinterface.setServerStatus("Error: Cannot listen on port " + port + " : " + e);
System.exit(1);
}
while (true) // infinite loop - loops once for each client
{
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept(); //waits here (forever) until a client connects
System.out.println("Server has just accepted socket connection from a client");
GlobalVariables.sinterface.setServerStatus("Server has just accepted socket connection from a client");
} catch (IOException e) {
System.out.println("Accept failed: " + e);
GlobalVariables.sinterface.setServerStatus("Accept failed: " + e);
break;
}
// Create the Handle Connection object - our new thread object - only create it
ThreadedHandleConnection con = new ThreadedHandleConnection(clientSocket);
if (con == null) //If it failed send and error message
{
try {
ObjectOutputStream os = new ObjectOutputStream(clientSocket.getOutputStream());
os.writeObject("error: Cannot open socket thread");
os.flush();
os.close();
} catch (Exception ex) //failed to even send an error message
{
System.out.println("Cannot send error back to client: " + ex);
GlobalVariables.sinterface.setServerStatus("Cannot send error back to client: " + ex);
}
} else {
con.start();
} // otherwise we have not failed to create the HandleConnection object
// start this thread now
}
try // do not get here at the moment
{
System.out.println("Closing server socket.");
GlobalVariables.sinterface.setServerStatus("Closing server socket.");
serverSocket.close();
} catch (IOException e) {
System.err.println("Could not close server socket. " + e.getMessage());
GlobalVariables.sinterface.setServerStatus("Could not close server socket. " + e.getMessage());
}
}
}
连接处理程序:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package tcpServer_package;
import java.net.*;
import java.io.*;
import java.util.*;
import busimesslogic_package.Functions;
/**
*
* @author wsserver
*/
public class ThreadedHandleConnection extends Thread {
private Socket clientSocket; // Client socket object
private ObjectInputStream is; // Input stream
private ObjectOutputStream os; // Output stream
// The constructor for the connecton handler
public ThreadedHandleConnection(Socket clientSocket) {
this.clientSocket = clientSocket;
}
// The main thread execution method
public void run() {
try {
this.is = new ObjectInputStream(clientSocket.getInputStream());
this.os = new ObjectOutputStream(clientSocket.getOutputStream());
while (this.readCommand()) {
}
} catch (IOException e) {
e.printStackTrace();
}
}
// Receive and process incoming command from client socket
private boolean readCommand() {
String wholeCommand = null;
try {
wholeCommand = (String) is.readObject();
} catch (Exception e) {
wholeCommand = null;
}
if (wholeCommand == null) {
this.closeSocket();
return false;
}
System.out.println("Received: "+wholeCommand);
//GET COMMAND PARAMETARS
String[] commParams = wholeCommand.split(";");
//GET COMMAND TYPE
int type = Integer.parseInt(commParams[0]);
//SELECT COMMAND PROCEDURE
Functions functions = new Functions();
String IPaddress = clientSocket.getRemoteSocketAddress().toString();
IPaddress = IPaddress.substring(IPaddress.indexOf("/")+1, IPaddress.indexOf(":"));
switch (type) {
case 1: {
String sendText = getTextToSend();
send(sendText);
break;
}
default:{
sendError("0;"+wholeCommand);
break;
}
}
System.gc();
return true;
}
// Send a message back through to the client socket as an Object
private void send(Object o) {
try {
System.out.println("Sending " + o);
this.os.writeObject(o);
this.os.flush();
} catch (Exception ex) {
ex.printStackTrace();
}
}
// Send a pre-formatted error message to the client
public void sendError(String msg) {
this.send("error:" + msg); //remember a string IS-A object!
}
// Close the client socket
public void closeSocket() //close the socket connection
{
try {
this.os.close();
this.is.close();
this.clientSocket.close();
} catch (Exception ex) {
System.err.println(ex.toString());
}
}
}
安卓客户端代码:
package com.example.zpbitolaoperator;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import android.util.Log;
public class TCPClient{
//Comunication variables
private static Socket socket;
private static ObjectOutputStream os;
private static ObjectInputStream is;
//Server parametars
static String serverIP;
static int port;
//Communication status
static boolean connectionStatus = false;
public static boolean connectToServer() {
try // open a new socket to port: and create streams
{
serverIP = GlobalVariables.serverIP;
port = GlobalVariables.portNo;
socket = new Socket(serverIP, port);
os = new ObjectOutputStream(socket.getOutputStream());
is = new ObjectInputStream(socket.getInputStream());
Log.d("DEBUG", "Connected to Server");
connectionStatus = true;
return true;
} catch (Exception ex) {
Log.d("DEBUG", "Failed to Connect to Server " +ex.toString(), ex.getCause());
connectionStatus = false;
return false;
}
}
public static boolean closeConnection(String message){
try{
socket.close();
Log.d("DEBUG", "Closed connection to Server");
return true;
} catch (Exception ex){
Log.d("DEBUG", "Failed to close connection to Server " +ex.toString(), ex.getCause());
return false;
}
}
private static String sendMessage(String message) {
String returnString;
send(message);
returnString = (String) receive();
if (returnString != null) {
Log.d("DEBUG", "Server returned: " + returnString);
}else{
return returnString = "ERROR";
}
return returnString;
}
// method to send a generic object.
private static void send(Object o) {
try {
Log.d("DEBUG", "Sending: " + o);
os.writeObject(o);
os.flush();
} catch (Exception ex) {
Log.d("DEBUG", "Sending to server " +ex.toString(), ex.getCause());
}
}
// method to receive a generic object.
private static Object receive() {
Object o = null;
try {
o = is.readObject();
} catch (Exception ex) {
Log.d("DEBUG", "Receive from server " +ex.toString(), ex.getCause());
}
return o;
}
/**
* Isprakja poraka do server
* @param message
* @return ili ERROR ili poraka
*/
public synchronized static String sendToServer(String message) {
String rez = "";
try {
rez = sendMessage(message);
} catch (Exception ex) {
Log.d("DEBUG", "Send to server " +ex.toString(), ex.getCause());
}
return rez;
}
public static boolean getCommunicationStatus(){
return connectionStatus;
}
}
我将字符串数据发送到我的服务器(comand;param1;param2....),服务器处理该数据并返回一些数据以执行 android 应用程序。android 应用程序是 TCP 客户端,java 应用程序是服务器。对于每个连接,服务器都会创建处理该连接的线程(无限)。问题是我的服务器不能在没有客户端先发送请求的情况下发送一些东西。ObjectInputStream readObject() 阻塞线程,直到客户端发送一些数据。我想使用同一个套接字向另一个方向发送(java -> android 和 android 应用程序发回一些数据)。我知道这可以通过打开另一个套接字来完成,其中 Android 将是服务器和 java 应用程序将是客户。这是可能的吗?如何?