Android socket聊天室

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/AmazingUU/article/details/52567036

效果图:

这里写图片描述

利用socket实现了简单的聊天室功能。首先要用java先写一个ServerSocket服务器

public class SocketTest {
    public static void main(String[] args) {

        try {
            //端口号从1-65535中任选一个,一般选择较大的
            ServerSocket serverSocket= new ServerSocket(12346);
            //阻塞线程
            Socket socket=serverSocket.accept();
            System.out.println("success");
    } catch (IOException e) {
        e.printStackTrace();
     }
   }
}

上面一段代码就可以创建一个ServerSocket服务器端,在浏览器里输入本机IP再加上端口号(我的是192.168.56.1:12346),就可以在android studio里看到success,代表连接成功.(浏览器里为什么会显示无法连接,可能是因为我没有写网页的html)

这里写图片描述

但是这样还是有问题,代码里我也写了accept()会阻塞线程,要在子线程里创建ServerSocket并且accept(),然后就是聊天室功能的具体逻辑了,我在代码里会注释,下面贴出完整代码

public class SocketTest {
    public static void main(String[] args) {
        new ServerListener().start();

//          try {
//              ServerSocket serverSocket= new ServerSocket(12346);
//              Socket socket=serverSocket.accept();
//              System.out.println("success");
//          } catch (IOException e) {
//              e.printStackTrace();
//          }
    }
}
//监听线程
public class ServerListener extends Thread {
    public void run() {
        try {
            ServerSocket serverSocket=new ServerSocket(12340);
            while(true){//循环监听连接
                Socket socket=serverSocket.accept();
                System.out.println("success");
                //将socket传递给聊天线程
                ChatSocket cs=new ChatSocket(socket);
                cs.start();
                ChatManager.getChatManager().add(cs);
            }
        } catch (Exception e) {
        }
    }
}
public class ChatSocket extends Thread {
    Socket socket;
    BufferedWriter bWriter;
    BufferedReader br;
    public ChatSocket(Socket socket) {
        this.socket=socket;
    }

    public void out(String out) { //发送数据
        try {
            bWriter=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            bWriter.write(out+"\n");//必须要加\n
            bWriter.flush();//这一句也要写,不然接收端收不到数据
            System.out.println("out: "+out);
//          bWriter.close();
        } catch (Exception e) {
        }
    }
    public void run() {  //接收数据
        try {
            br=new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
            String line=null;
            //readLine是以\n为结束,所以接收端发送给服务器的消息要以\n结束
            while ((line=br.readLine())!=null) {
                ChatManager.getChatManager().publish(this, line);
                System.out.println("input: "+line);
            }
            br.close();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}
//聊天管理类
public class ChatManager {
    private ChatManager() {}
    private static final ChatManager cm=new ChatManager();

    public static ChatManager getChatManager() {
        return cm;
    }

    Vector<ChatSocket> vector=new Vector<ChatSocket>();
    //将ChatSocket添加进ChatManager
    public void add(ChatSocket cs) {
        vector.add(cs);
    }
    //向ChatManager里的ChatSocket发送消息
    public void publish(ChatSocket cs,String out) {
        for (int i = 0; i < vector.size(); i++) {
            ChatSocket cSocket=vector.get(i);
            if (!cs.equals(cSocket)) {//当前发送的socket就不用再接受消息了
                cSocket.out(out);
            }
        }
    }
}

上面就是socket的服务器端,下面讲android端,直接上代码

package com.example.administrator.serversockettest;

import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

public class MainActivity extends AppCompatActivity {
    private Button btn_connect, btn_send;
    private EditText edIP, edContent;
    private TextView tvContent;
    private String IP;//本机IP 192.168.56.1

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_connect = (Button) findViewById(R.id.btn_connect);
        btn_send = (Button) findViewById(R.id.btn_send);
        edIP = (EditText) findViewById(R.id.edIP);
        edContent = (EditText) findViewById(R.id.edContent);
        tvContent = (TextView) findViewById(R.id.tvContent);

        btn_connect.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                IP = edIP.getText().toString();
                connect();
            }
        });

        btn_send.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                send();
            }
        });
    }

    private Socket socket = null;
    private BufferedWriter writer = null;
    private BufferedReader reader = null;

    public void connect() { //连接线程
        AsyncTask<Void, String, Void> read = new AsyncTask<Void, String, Void>() {
            @Override
            protected Void doInBackground(Void... voids) { //不能进行UI操作
                try {
                    socket = new Socket(IP, 12340);
                    writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
                    reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    publishProgress("success");//调用publishProgress(),会进入onProgressUpdate()
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    String line;
                    //readLine是以\n为结束,所以服务器发送的消息要以\n结束
                    while ((line=reader.readLine())!=null) {
                        publishProgress(line);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return null;
            }

            @Override
            protected void onProgressUpdate(String... values) { //可以进行UI操作
                tvContent.append("other: " + values[0] + "\n");
                super.onProgressUpdate(values);
            }
        };
        read.execute();
    }

    public void send() {
        try {
            tvContent.append("me: " + edContent.getText().toString() + "\n");
            writer.write(edContent.getText().toString()+"\n");//以\n为结尾
            writer.flush();//这句一定要加
            edContent.setText("");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

xml文件

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.administrator.serversockettest.MainActivity">

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">

        <EditText
            android:id="@+id/edIP"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="3"/>

        <Button
            android:id="@+id/btn_connect"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="connect" />
    </TableRow>

    <TextView
        android:id="@+id/tvContent"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="20"
        android:text="" />

    <EditText
        android:id="@+id/edContent"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="2"
        android:hint="edit here"/>

    <Button
        android:id="@+id/btn_send"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="2"
        android:text="send" />
</TableLayout>

因为socket需要联网,所以还要在AndroidManifest里添加权限

<uses-permission android:name="android.permission.INTERNET"/>

注:输出流的发送的消息必须要以\n为结束,并且write()之后要调用flush(),否则接收端接收不到消息。

下面是android完整工程,java服务器我就不放了

http://download.csdn.net/detail/amazinguu/9634287

猜你喜欢

转载自blog.csdn.net/AmazingUU/article/details/52567036