从客户端向服务器发送消息

时间:2018-03-26 14:55:36

标签: java android server chat serversocket

我与Android工作室制作的Android客户端和使用Java制作的服务器进行了聊天。

如何从客户端向服务器发送消息?并从服务器广播消息到所有客户端?

示例:

  1. 客户#1发送:您好
  2. 服务器接收:您好
  3. 服务器将消息(Hello)发送给所有其他客户端。
  4. 主服务器:

    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" />
    

2 个答案:

答案 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。

编写的