我使用this (Android TCP Connection Enhanced)教程创建简单的JAVA TCPServer和Android TCPClient。它工作得很完美,但使用此代码我可以同时只将一个设备连接到服务器。如何更改以连接多个设备?
public class Constants {
public static final String CLOSED_CONNECTION = "kazy_closed_connection";
public static final String LOGIN_NAME = "kazy_login_name";
}
public class MainScreen extends JFrame {
/**
*
*/
private static final long serialVersionUID = 8399514248326995812L;
private JTextArea messagesArea;
private JButton sendButton;
private JTextField message;
private JButton startServer;
private JButton stopServer;
private TcpServer mServer;
public MainScreen() {
super("MainScreen");
JPanel panelFields = new JPanel();
panelFields.setLayout(new BoxLayout(panelFields, BoxLayout.X_AXIS));
JPanel panelFields2 = new JPanel();
panelFields2.setLayout(new BoxLayout(panelFields2, BoxLayout.X_AXIS));
// here we will have the text messages screen
messagesArea = new JTextArea();
messagesArea.setColumns(30);
messagesArea.setRows(10);
messagesArea.setEditable(false);
sendButton = new JButton("Send");
sendButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// get the message from the text view
String messageText = message.getText();
// add message to the message area
messagesArea.append("\n" + messageText);
if (mServer != null) {
// send the message to the client
mServer.sendMessage(messageText);
}
// clear text
message.setText("");
}
});
startServer = new JButton("Start");
startServer.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// creates the object OnMessageReceived asked by the TCPServer
// constructor
mServer = new TcpServer(new TcpServer.OnMessageReceived() {
@Override
// this method declared in the interface from TCPServer
// class is implemented here
// this method is actually a callback method, because it
// will run every time when it will be called from
// TCPServer class (at while)
public void messageReceived(String message) {
messagesArea.append("\n " + message);
}
});
mServer.start();
// disable the start button and enable the stop one
startServer.setEnabled(false);
stopServer.setEnabled(true);
}
});
stopServer = new JButton("Stop");
stopServer.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (mServer != null) {
mServer.close();
}
// disable the stop button and enable the start one
startServer.setEnabled(true);
stopServer.setEnabled(false);
}
});
// the box where the user enters the text (EditText is called in
// Android)
message = new JTextField();
message.setSize(200, 20);
// add the buttons and the text fields to the panel
panelFields.add(messagesArea);
panelFields.add(startServer);
panelFields.add(stopServer);
panelFields2.add(message);
panelFields2.add(sendButton);
getContentPane().add(panelFields);
getContentPane().add(panelFields2);
getContentPane().setLayout(
new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
setSize(300, 170);
setVisible(true);
}
}
public class TcpServer extends Thread {
public static final int SERVERPORT = 4444;
// while this is true the server will run
private boolean running = false;
// used to send messages
private PrintWriter bufferSender;
// callback used to notify new messages received
private OnMessageReceived messageListener;
private ServerSocket serverSocket;
private Socket client;
/**
* Constructor of the class
*
* @param messageListener
* listens for the messages
*/
public TcpServer(OnMessageReceived messageListener) {
this.messageListener = messageListener;
}
public static void main(String[] args) {
// opens the window where the messages will be received and sent
MainScreen frame = new MainScreen();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
/**
* Close the server
*/
public void close() {
running = false;
if (bufferSender != null) {
bufferSender.flush();
bufferSender.close();
bufferSender = null;
}
try {
client.close();
serverSocket.close();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("S: Done.");
serverSocket = null;
client = null;
}
/**
* Method to send the messages from server to client
*
* @param message
* the message sent by the server
*/
public void sendMessage(String message) {
if (bufferSender != null && !bufferSender.checkError()) {
bufferSender.println(message);
bufferSender.flush();
}
}
public boolean hasCommand(String message) {
if (message != null) {
if (message.contains(Constants.CLOSED_CONNECTION)) {
messageListener.messageReceived(message.replaceAll(
Constants.CLOSED_CONNECTION, "")
+ " disconnected");
// close the server connection if we have this command and
// rebuild a new one
close();
runServer();
return true;
} else if (message.contains(Constants.LOGIN_NAME)) {
messageListener.messageReceived(message.replaceAll(
Constants.LOGIN_NAME, "") + " connected");
return true;
}
}
return false;
}
/**
* Builds a new server connection
*/
private void runServer() {
running = true;
try {
System.out.println("S: Connecting...");
// create a server socket. A server socket waits for requests to
// come in over the network.
serverSocket = new ServerSocket(SERVERPORT);
// create client socket... the method accept() listens for a
// connection to be made to this socket and accepts it.
client = serverSocket.accept();
System.out.println("S: Receiving...");
try {
// sends the message to the client
bufferSender = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(client.getOutputStream())), true);
// read the message received from client
BufferedReader in = new BufferedReader(new InputStreamReader(
client.getInputStream()));
// in this while we wait to receive messages from client (it's
// an infinite loop)
// this while it's like a listener for messages
while (running) {
String message = null;
try {
message = in.readLine();
} catch (IOException e) {
System.out.println("Error reading message: "
+ e.getMessage());
}
if (hasCommand(message)) {
continue;
}
if (message != null && messageListener != null) {
// call the method messageReceived from ServerBoard
// class
messageListener.messageReceived(message);
}
}
} catch (Exception e) {
System.out.println("S: Error");
e.printStackTrace();
}
} catch (Exception e) {
System.out.println("S: Error");
e.printStackTrace();
}
}
@Override
public void run() {
super.run();
runServer();
}
// Declare the interface. The method messageReceived(String message) will
// must be implemented in the ServerBoard
// class at on startServer button click
public interface OnMessageReceived {
public void messageReceived(String message);
}
}
public class TCPClient {
public static final String SERVER_IP = "192.168.0.102"; // your computer IP
// address
public static final int SERVER_PORT = 4444;
// message to send to the server
private String mServerMessage;
// sends message received notifications
private OnMessageReceived mMessageListener = null;
// while this is true, the server will continue running
private boolean mRun = false;
// used to send messages
private PrintWriter mBufferOut;
// used to read messages from the server
private BufferedReader mBufferIn;
private String uid;
/**
* Constructor of the class. OnMessagedReceived listens for the messages
* received from server
*/
public TCPClient(OnMessageReceived listener) {
mMessageListener = listener;
}
/**
* Sends the message entered by client to the server
*
* @param message
* text entered by client
*/
public void sendMessage(String message) {
if (mBufferOut != null && !mBufferOut.checkError()) {
mBufferOut.println(message);
mBufferOut.flush();
}
}
/**
* Close the connection and release the members
*/
public void stopClient() {
// send mesage that we are closing the connection
TelephonyManager tManager = (TelephonyManager) MyApplication.getInstance().getSystemService(Context.TELEPHONY_SERVICE);
uid = tManager.getDeviceId();
sendMessage(Constants.CLOSED_CONNECTION + "id: " + uid);
mRun = false;
if (mBufferOut != null) {
mBufferOut.flush();
mBufferOut.close();
}
mMessageListener = null;
mBufferIn = null;
mBufferOut = null;
mServerMessage = null;
}
public void run() {
mRun = true;
try {
// here you must put your computer's IP address.
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
MyLog.e("TCP Client", "C: Connecting...");
// create a socket to make the connection with the server
Socket socket = new Socket(serverAddr, SERVER_PORT);
try {
// sends the message to the server
mBufferOut = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())), true);
// receives the message which the server sends back
mBufferIn = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
// send login name
TelephonyManager tManager = (TelephonyManager) MyApplication.getInstance().getSystemService(Context.TELEPHONY_SERVICE);
uid = tManager.getDeviceId();
sendMessage(Constants.LOGIN_NAME + "id: " + uid);
// in this while the client listens for the messages sent by the
// server
while (mRun) {
mServerMessage = mBufferIn.readLine();
if (mServerMessage != null && mMessageListener != null) {
// call the method messageReceived from MyActivity class
mMessageListener.messageReceived(mServerMessage);
}
}
MyLog.e("RESPONSE FROM SERVER", "S: Received Message: '"
+ mServerMessage + "'");
} catch (Exception e) {
MyLog.e("TCP", "S: Error", e);
} finally {
// the socket must be closed. It is not possible to reconnect to
// this socket
// after it is closed, which means a new socket instance has to
// be created.
socket.close();
}
} catch (Exception e) {
MyLog.e("TCP", "C: Error", e);
}
}
// Declare the interface. The method messageReceived(String message) will
// must be implemented in the MyActivity
// class at on asynckTask doInBackground
public interface OnMessageReceived {
public void messageReceived(String message);
}
}
public class Constants {
public static final String CLOSED_CONNECTION = "kazy_closed_connection";
public static final String LOGIN_NAME = "kazy_login_name";
}
@Override
protected void onPause() {
super.onPause();
if(connect != null) {
connect.cancel(true);
}
if(mTcpClient != null) {
MyLog.d(TAG, "stopClient");
mTcpClient.stopClient();
mTcpClient = null;
}
}
public class ConnectTask extends AsyncTask<String,String,TCPClient> {
@Override
protected TCPClient doInBackground(String... message) {
MyLog.d(TAG, "doInBackground");
//we create a TCPClient object and
mTcpClient = new TCPClient(new TCPClient.OnMessageReceived() {
@Override
//here the messageReceived method is implemented
public void messageReceived(String message) {
//this method calls the onProgressUpdate
publishProgress(message);
}
});
mTcpClient.run();
return null;
}
@Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
MyLog.d(TAG, "onProgressUpdate");
View view = adapter.getChildView(0, 0, false, null, null);
TextView text = (TextView) view.findViewById(R.id.betChildOdd);
child2.get(0).get(0).put("OLD", text.getText().toString());
child2.get(0).get(0).put(CONVERTED_ODDS, values[0].toString());
child2.get(0).get(0).put("CHANGE", "TRUE");
adapter.notifyDataSetChanged();
}
}
答案 0 :(得分:6)
我没有完成所有代码,但我想到的第一件事是:您是否基于多线程服务器架构构建应用程序?对于我在代码中看到的内容,我注意到你没有将socket.accept()之后的执行委托给另一个线程,这就是为什么你不能同时回答多个客户端的原因。
请记住,您需要处理并发访问相同数据结构所产生的竞争条件。
这是您应该为TCP服务器遵循的模式:http://tutorials.jenkov.com/java-multithreaded-servers/multithreaded-server.html