我与Android工作室制作的Android客户端和使用Java制作的服务器进行了聊天。
如何从客户端向服务器发送消息?并从服务器广播消息到所有客户端?
示例:
主服务器:
package server1;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.*;
public class Server1 {
public static void main(String[] args) throws IOException {
Socket newsock = null;
int nreq = 1;
try
{
ServerSocket sock = new ServerSocket (3000);
for (;;)
{
newsock = sock.accept();
System.out.println("Creating thread ...");
Thread t = new ThreadHandler(newsock,nreq);
t.start();
}
}
catch (Exception e)
{
System.out.println("IO error " + e);
}
System.out.println("End!");
BufferedReader in=new BufferedReader(new InputStreamReader(newsock.getInputStream()));
PrintWriter out=new PrintWriter(newsock.getOutputStream(),true);
}
}
ThreadHandler(服务器):
package server1;
import java.io.*;
import java.net.*;
class ThreadHandler extends Thread {
Socket newsock;
int n;
ThreadHandler(Socket s, int v) {
newsock = s;
n = v;
}
public void run() {
try {
PrintWriter outp = new PrintWriter(newsock.getOutputStream(), true);
BufferedReader inp = new BufferedReader(new InputStreamReader(
newsock.getInputStream()));
outp.println("Hello :: enter QUIT to exit \n");
boolean more_data = true;
String line;
while (more_data) {
line = inp.readLine();
System.out.println("Message '" + line + "' echoed back to
client.");
if (line == null) {
System.out.println("line = null");
more_data = false;
} else {
outp.println("From server: " + line + ". \n");
if (line.trim().equals("QUIT"))
more_data = false;
}
}
newsock.close();
System.out.println("Disconnected from client number: " + n);
} catch (Exception e) {
System.out.println("IO error " + e);
}
}
}
Android MainActivity.java:
package com.example.mirko.chatclient;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
public class MainActivity extends AppCompatActivity {
TextView chatzone;
EditText msg;
Button btninvio;
Socket socket;
PrintWriter out;
BufferedReader in;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final int PORTA=3000;
final String IP = "192.168.1.2";
try {
socket=new Socket(IP,PORTA);
} catch (IOException e) {
e.printStackTrace();
}
//si connette al server
chatzone= findViewById(R.id.chatzone);
msg= findViewById(R.id.msg);
btninvio=findViewById(R.id.btninvia);
//si dichiara i componenti
try {
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
try {
out= new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
} catch (IOException e) {
e.printStackTrace();
}
}
public void premuto(View v)
{
String messaggio=msg.getText().toString();
out.println(messaggio);
}
}
Android xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.mirko.chatclient.MainActivity">
<TextView
android:id="@+id/chatzone"
android:layout_width="343dp"
android:layout_height="309dp"
android:layout_marginEnd="24dp"
android:layout_marginStart="24dp"
android:layout_marginTop="16dp"
android:text="@string/chatzone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btninvia"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="32dp"
android:layout_marginEnd="148dp"
android:onClick="premuto"
android:text="@string/invia"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<EditText
android:id="@+id/msg"
android:layout_width="344dp"
android:layout_height="43dp"
android:layout_marginBottom="32dp"
android:layout_marginEnd="24dp"
android:layout_marginStart="24dp"
android:layout_marginTop="32dp"
android:ems="10"
android:inputType="text"
android:labelFor="@+id/msg"
android:text="@string/msg"
app:layout_constraintBottom_toTopOf="@+id/btninvia"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/chatzone" />
答案 0 :(得分:0)
您可以使用Ably之类的PaaS解决方案,该解决方案可在WebSockets下运行。这将使您的客户端和服务器连接到实时平台,并且只要您的某个客户端向平台发布消息,就可以将其实时推送到所有其他客户端(如果需要,包括您的服务器)。这不仅可以消除在服务器上执行此操作的开销,还可以抽象出websockets实现,这样您就可以专注于应用程序的业务逻辑。
基本上,它使用Pub / Sub消息传递模式,其中数据的发布者和订阅者都连接到实时平台,并且完全由平台处理已发布数据的扇出。使用Android客户端查看此tutorial。
答案 1 :(得分:0)
您的服务器代码存在逻辑问题。您为每个客户端连接启动一个新线程。您的ThreadHandler读取和写入该单个客户端。它没有任何其他可能的客户的信息。
您的服务器必须有一个&#34;主线程&#34;它处理客户之间的通信。每个客户端线程都应该有一个FIFO队列用于出站消息。服务器需要保留传入消息的中央FIFO队列和每个客户端出站消息队列的指针列表。客户端线程从其套接字读取消息,然后将其放入中央传入队列。 &#34;主线程&#34;从该队列中读取消息并将它们放入每个客户端线程的outbounds队列中。所有这一切都必须正确同步。
因此,您的客户端线程从套接字读取消息并将它们放入公共队列,然后从其自己的出站队列中读取消息并将它们写入套接字。主线程从公共传入队列中读取消息,并将它们写入单个客户端线程的出站队列。
一般来说,你试图解决的问题非常困难。除非这对你来说是纯粹的学习经验,否则你可以失败,你不应该建立自己的经验。使用现成的东西,如前面建议的那样或https://github.com/tinode/chat
此外,Java不是此类服务器端应用程序的最佳语言。大多数此类应用程序都是用Erlang(https://github.com/esl/MongooseIM)和Go。
编写的