TCP服务器 - 服务器通信

时间:2013-07-03 13:10:50

标签: java android tcp

我正在开发一个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());
        }
    }
}

Android客户端代码:

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;
    }
}

我将String数据发送到我的服务器(comand; param1; param2 ....),数据并返回一些数据的服务器进程做android应用程序。 android应用程序是TCP客户端,java应用程序是服务器。对于每个连接,服务器都会创建处理该连接的线程(无限)。问题是我的服务器无法在没有客户端首先发送请求的情况下发送内容。 ObjectInputStream readObject()阻塞线程,直到客户端发送一些数据。我想使用相同的套接字向另一个方向发送(java - > android和android应用程序发回一些数据)。我知道这可以通过打开另一个套接字来完成,其中Android将是服务器和java申请将是客户。这是可行的吗?

1 个答案:

答案 0 :(得分:0)

如果您希望能够同时从客户端接收数据将数据发送到客户端,那么您必须为每个客户端使用两个线程(一个用于接收,一个用于发送)或使用non-blocking IO