套接字上的Java简单客户机-服务器通信
我正在尝试为Android编写一个应用程序来连接我的Java服务器并远程控制它(只需运行Media Player或类似的东西)。 因为我从来没有写过任何套接字连接,所以我想我应该从一些非常简单的事情开始——只发送短消息。我的问题是我发送的第一条信息是正确的。当我尝试发送另一条消息时,它并没有到达服务器。 这是我的密码 Client.java套接字上的Java简单客户机-服务器通信,java,sockets,server,client,Java,Sockets,Server,Client,我正在尝试为Android编写一个应用程序来连接我的Java服务器并远程控制它(只需运行Media Player或类似的东西)。 因为我从来没有写过任何套接字连接,所以我想我应该从一些非常简单的事情开始——只发送短消息。我的问题是我发送的第一条信息是正确的。当我尝试发送另一条消息时,它并没有到达服务器。 这是我的密码 Client.java public class Client implements Runnable { private Socket connection; p
public class Client implements Runnable
{
private Socket connection;
private Long id;
private InputStream is;
public Boolean done;
DataInputStream dIn ;
public Client(Socket conn, Long ids) throws IOException
{
connection = conn;
is = conn.getInputStream();
id = ids;
dIn = new DataInputStream(is);
done = false;
}
public Socket getConnection()
{
return connection;
}
public void setConnection(Socket connection)
{
this.connection = connection;
}
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
@Override
public void run()
{
String msg = "";
while(!msg.equals("exit"))
{
try
{
if(is.available() >0)
{
int data =0;
StringBuilder sb = new StringBuilder();
while(data >=0)
{
data = dIn.read();
char c = (char) data;
sb.append(c);
}
System.out.println(sb.toString());
}
}
catch (IOException e) {
done = true;
e.printStackTrace();
}
}
}
}
现在是Server.java
package tcp;
public class Server implements Runnable {
private ServerSocket serverSocket;
private final static int SERVER_PORT = 6879;
private ServerManager serverManager;
InputStreamReader inputStreamReader;
BufferedReader bufferedReader;
public Server(ServerManager serverManager)
{
this.serverManager = serverManager;
}
@Override
public void run()
{
try
{
serverSocket = new ServerSocket(SERVER_PORT);
Log.log("Server został uruchomiony...");
addConnection.run();
}
catch (IOException e) {
Log.log(e.getMessage());
Log.logStack(e);
}
}
Runnable addConnection = () -> {
Log.log("Uruchomiono wątek oczekiwania na połączenie");
try {
while(true)
{
Socket connection = serverSocket.accept();
serverManager.addClient(connection);
InetAddress ia = connection.getInetAddress();
Log.log("Dodano klienta: "+ia.toString());
}
} catch (Exception e)
{
Log.log(e.getMessage());
Log.logStack(e);
}
};
}
和ServerManager.java
public class ServerManager implements Runnable
{
private Server server;
private HashMap<Long,Client> clients;
private Long lastId = Long.valueOf(0);
private Mutex clientsMutex = new Mutex();
@Override
public void run()
{
clients = new HashMap<>();
server = new Server(this);
server.run();
}
public void addClient(Socket conn) throws IOException
{
try
{
clientsMutex.acquire();
++lastId;
Client cd = new Client(conn,lastId);
clients.put(lastId, cd);
Thread thread = new Thread(cd);
thread.start();
} catch (InterruptedException e)
{
Log.log(e.getMessage());
Log.logStack(e);
}
finally
{
clientsMutex.release();
}
}
}
公共类ServerManager实现可运行
{
专用服务器;
私有HashMap客户端;
private Long lastId=Long.valueOf(0);
私有互斥体clientsMutex=新互斥体();
@凌驾
公开募捐
{
clients=newhashmap();
服务器=新服务器(此服务器);
server.run();
}
public void addClient(套接字连接)引发IOException
{
尝试
{
clientsMutex.acquire();
++拉斯蒂德;
客户机cd=新客户机(conn,lastId);
clients.put(lastId,cd);
螺纹=新螺纹(cd);
thread.start();
}捕捉(中断异常e)
{
Log.Log(如getMessage());
Log.logStack(e);
}
最后
{
clientsMutex.release();
}
}
}
当然还有客户端代码:
public class SlimpleTextClientActivity extends Activity {
private Socket client;
private PrintWriter printwriter;
private EditText textField;
private Button button;
private String messsage;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_slimple_text_client);
textField = (EditText) findViewById(R.id.editText1); // reference to the text field
button = (Button) findViewById(R.id.button1); // reference to the send button
establishConnection();
// Button press event listener
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
messsage = textField.getText().toString(); // get the text message on the text field
textField.setText(""); // Reset the text field to blank
SendMessage sendMessageTask = new SendMessage();
sendMessageTask.execute();
}
});
}
private void establishConnection() {
EstablishConnection est = new EstablishConnection();
est.execute();
}
private class EstablishConnection extends AsyncTask<Void, Void, Void>
{
@Override
protected Void doInBackground(Void... params) {
try {
client = new Socket("192.168.0.12", 6879); // connect to the server
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
return null;
}
}
private class SendMessage extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
try {
printwriter = new PrintWriter(client.getOutputStream(), true);
printwriter.write(messsage); // write the message to output stream
printwriter.flush();
printwriter.close();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.slimple_text_client, menu);
return true;
}
}
public类SlimpleTextClientActivity扩展活动{
专用套接字客户端;
私人印刷作家;
私有编辑文本字段;
私人按钮;
私有字符串消息;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity\u slimple\u text\u客户端);
textField=(EditText)findViewById(R.id.editText1);//对文本字段的引用
button=(button)findViewById(R.id.button1);//对发送按钮的引用
建立连接();
//按钮按下事件侦听器
setOnClickListener(新视图.OnClickListener(){
公共void onClick(视图v){
message=textField.getText().toString();//获取文本字段上的文本消息
textField.setText(“”;//将文本字段重置为空白
SendMessage sendMessageTask=新建SendMessage();
sendMessageTask.execute();
}
});
}
私有连接(){
est=新的EstablishConnection();
est.execute();
}
私有类连接扩展异步任务
{
@凌驾
受保护的Void doInBackground(Void…参数){
试一试{
client=newsocket(“192.168.0.12”,6879);//连接到服务器
}捕获(未知后异常e){
e、 printStackTrace();
}捕获(IOE异常){
e、 printStackTrace();
}最后{
}
返回null;
}
}
私有类SendMessage扩展异步任务{
@凌驾
受保护的Void doInBackground(Void…参数){
试一试{
printwriter=新的printwriter(client.getOutputStream(),true);
write(message);//将消息写入输出流
printwriter.flush();
printwriter.close();
}捕获(IOE异常){
e、 printStackTrace();
}
返回null;
}
}
@凌驾
公共布尔onCreateOptions菜单(菜单){
//为菜单充气;这会将项目添加到操作栏(如果存在)。
getMenuInflater().充气(R.menu.slimple_text_客户端,菜单);
返回true;
}
}
您在发送一条消息后正在关闭连接。因此,您需要打开新连接以发送新消息。或者在两端调整您的协议以保持连接打开。哦,我忘了添加:任何使用DataInputStream的尝试。readXXX()以EOFEException结束摆脱available()
测试。这简直是浪费时间。您没有其他事情要做,所以只要在read()中阻塞。
当if调用可用的方法并尝试读取尽可能多的数据时,我将获得EOF异常。我不明白如何保持联系…我不明白。我认为在我的代码中,我正在打开一个连接,它仍然是打开的,直到我手动关闭它。所以如果我想保持连接,我应该怎么做?