无法为单个java服务器管理多个客户端(android设备)
我需要我的服务器跟踪每个客户端的连接。有人建议我使用线程。因此,我试图实现的是为每个客户机创建一个线程,该线程应该一直运行到客户机连接存在为止。但是,对于任何客户端发送的每条消息,都会在doInBackground()函数中创建一个新的客户端连接。因此,我不再为一个客户端使用一个线程,而是为发送到服务器的任何客户端消息使用一个线程。您能推荐一种方法,让我的服务器能够区分从不同客户端发送的不同消息吗 Java服务器代码:无法为单个java服务器管理多个客户端(android设备),java,android,multithreading,client-server,Java,Android,Multithreading,Client Server,我需要我的服务器跟踪每个客户端的连接。有人建议我使用线程。因此,我试图实现的是为每个客户机创建一个线程,该线程应该一直运行到客户机连接存在为止。但是,对于任何客户端发送的每条消息,都会在doInBackground()函数中创建一个新的客户端连接。因此,我不再为一个客户端使用一个线程,而是为发送到服务器的任何客户端消息使用一个线程。您能推荐一种方法,让我的服务器能够区分从不同客户端发送的不同消息吗 Java服务器代码: package com.nss.academyassistserver;
package com.nss.academyassistserver;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class AcademyAssistServer {
public static ServerSocket serverSocket;
public static Socket clientSocket;
static final int PORT = 4444;
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
serverSocket = new ServerSocket(PORT); // Server socket
} catch (IOException e) {
System.out.println("Could not listen on port: "+PORT+" \n");
}
System.out.println("Server started. Listening to the port "+PORT);
while (true) {
try {
clientSocket = serverSocket.accept();
System.out.println("New connection accepted."); // accept the client connection
} catch (IOException ex) {
System.out.println("Problem in message reading");
}
//new thread for a client
new EchoThread(clientSocket).start();
}
}
}
class EchoThread extends Thread {
InputStreamReader inputStreamReader;
BufferedReader bufferedReader;
String fromClient;
Socket clientSocket;
public EchoThread(Socket clientSocket) {
this.clientSocket = clientSocket;
}
public void run() {
try {
inputStreamReader = new InputStreamReader(clientSocket.getInputStream());
bufferedReader = new BufferedReader(inputStreamReader); // get the client message
} catch (IOException e) {
return;
}
while (!Thread.currentThread().isInterrupted()) {
System.out.println("I am thread " + Thread.currentThread().getId());
try {
fromClient = bufferedReader.readLine();
if ((fromClient == null) || fromClient.equalsIgnoreCase("exit")) {
System.out.println("You're welcome, bye!");
return;
} else {
System.out.println(fromClient);
Thread.currentThread().interrupt();
}
} catch (IOException e) {
e.printStackTrace();
return;
}
}
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端活动代码:
package com.nss.academyassist;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Locale;
//import statements for client
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.Toast;
//import statements for client
import android.os.AsyncTask;
public class MainActivity extends Activity implements OnClickListener {
EditText question;
//Client sockets
private Socket client;
private PrintWriter printwriter;
private String toTag;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
question = (EditText)findViewById(R.id.editText1);
Button query = (Button)findViewById(R.id.button2);
query.setOnClickListener(this);
}
private class SendMessage extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
try {
client = new Socket("Server IP Address", 4444);
printwriter = new PrintWriter(client.getOutputStream(), true);
printwriter.write(toTag); // write the message to output stream
printwriter.flush();
printwriter.close();
client.close(); // closing the connection
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
public void onClick(View v)
{
switch(v.getId())
{
case R.id.button2:
toTag = question.getText().toString();
// Output the result
Toast.makeText(getApplicationContext(), toTag,
Toast.LENGTH_LONG).show();
//Invoke the execute method of AsynTask, which will run the doInBackground method of SendMessage Class
SendMessage sendMessageTask = new SendMessage();
sendMessageTask.execute();
break;
}
}
}
package com.nss.academyassist;
导入java.util.ArrayList;
导入java.util.array;
导入java.util.Locale;
//客户端的导入语句
导入java.io.IOException;
导入java.io.PrintWriter;
导入java.net.Socket;
导入java.net.UnknownHostException;
导入android.app.Activity;
导入android.content.Intent;
导入android.os.Bundle;
导入android.view.Menu;
导入android.view.MenuItem;
导入android.view.view;
导入android.view.view.OnClickListener;
导入android.view.Window;
导入android.view.WindowManager;
导入android.widget.Button;
导入android.widget.EditText;
导入android.widget.ImageButton;
导入android.widget.Toast;
//客户端的导入语句
导入android.os.AsyncTask;
公共类MainActivity扩展活动实现OnClickListener{
编辑文本问题;
//客户端套接字
专用套接字客户端;
私人印刷作家;
私有字符串toTag;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
问题=(EditText)findViewById(R.id.editText1);
按钮查询=(按钮)findViewById(R.id.button2);
query.setOnClickListener(this);
}
私有类SendMessage扩展异步任务{
@凌驾
受保护的Void doInBackground(Void…参数){
试一试{
客户端=新套接字(“服务器IP地址”,4444);
printwriter=新的printwriter(client.getOutputStream(),true);
write(toTag);//将消息写入输出流
printwriter.flush();
printwriter.close();
client.close();//关闭连接
}捕获(未知后异常e){
e、 printStackTrace();
}捕获(IOE异常){
e、 printStackTrace();
}
返回null;
}
}
公共void onClick(视图v)
{
开关(v.getId())
{
案例R.id.按钮2:
toTag=question.getText().toString();
//输出结果
Toast.makeText(getApplicationContext(),toTag,
Toast.LENGTH_LONG).show();
//调用AsynTask的execute方法,该方法将运行SendMessage类的doInBackground方法
SendMessage sendMessageTask=新建SendMessage();
sendMessageTask.execute();
打破
}
}
}
您可以使用IP通知客户端。使用
clientSocket.getInetAddress().getHostAddress()
您还可以在android代码中保持客户端不关闭。例如,您可以在
onCreate
中打开Socket
,然后在onestory
中关闭它。问题的原因在于客户端代码。使用newsocket(..)
您的客户端将在每次向服务器发送标记时创建一个新连接。因此,您可以创建一个可重用的连接:
public class MainActivity extends Activity implements OnClickListener {
/* .. your other variables .. */
private Socket client;
private PrintWriter printwriter;
@Override
protected void onCreate(Bundle savedInstanceState) {
/* .. no change here .. */
}
public void onStart()
{
if(this.client != null)
{
try {
client = new Socket("Server IP Address", 4444);
printwriter = new PrintWriter(client.getOutputStream(), true);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void onClose()
{
this.printwriter.close();
this.printwriter = null;
this.client.close();
this.client = null;
}
private class SendMessage extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
try {
printwriter.write(toTag); // write the message to output stream
printwriter.write("\n"); // delimiter
printwriter.flush();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
public void onClick(View v)
{
switch(v.getId())
{
case R.id.button2:
toTag = question.getText().toString();
// Output the result
Toast.makeText(getApplicationContext(), toTag,
Toast.LENGTH_LONG).show();
//Invoke the execute method of AsynTask, which will run the doInBackground method of SendMessage Class
SendMessage sendMessageTask = new SendMessage();
sendMessageTask.execute();
break;
}
}
}
public类MainActivity扩展活动实现OnClickListener{
/*…您的其他变量*/
专用套接字客户端;
私人印刷作家;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
/*……这里没有变化*/
}
public void onStart()
{
如果(this.client!=null)
{
试一试{
客户端=新套接字(“服务器IP地址”,4444);
printwriter=新的printwriter(client.getOutputStream(),true);
}捕获(未知后异常e){
e、 printStackTrace();
}捕获(IOE异常){
e、 printStackTrace();
}
}
}
公开作废
{
这是.printwriter.close();
this.printwriter=null;
this.client.close();
this.client=null;
}
私有类SendMessage扩展异步任务{
@凌驾
受保护的Void doInBackground(Void…参数){
试一试{
write(toTag);//将消息写入输出流
printwriter.write(“\n”);//分隔符
printwriter.flush();
}捕获(IOE异常){
e、 printStackTrace();
}
返回null;
}
}
公共void onClick(视图v)
{
开关(v.getId())
{
案例R.id.按钮2:
toTag=question.getText().toString();
//输出结果
Toast.makeText(getApplicationContext(),toTag,
Toast.LENGTH_LONG).show();
//调用AsynTask的execute方法,该方法将运行SendMessage类的doInBackground方法
SendMessage sendMessageTask=新建SendMessage();
森德梅斯