• QQ
  • nahooten@sina.com
  • 常州市九洲新世界花苑15-2

Android

Android运用socket即时通信的实现

原创内容,转载请注明原文网址:http://homeqin.cn/a/wenzhangboke/jishutiandi/Android/2019/0929/665.html

 
 
 
一、服务器
 
 
 
常州网站开发建设思路:
 
 
 
首先建立服务器,用一个死轮回等候几何个客户端的持续。一旦有客户端持续,就把客户端增加到鸠合中间,并且启动一个新的线程来连结长持续,监控客户端发来的信息。一旦汲取到有客户端发来的信息,就举行包装后遍历鸠合,把包装好的信息发送给每一个客户端。
 
 
 
代码以下:
 
 
 
/**
 
 * Tcp通信服务器
 
 * @author Devin Chen
 
 *
 
 */
 
public class CSServer {
 
private static final int PORT = 8888;
 
private List<Socket> mClientList = new ArrayList<Socket>();
 
private ServerSocket server = null;
 
private ExecutorService mExecutors = null; // 线程池对象
 
 
 
public static void main(String[] args) {
 
new CSServer();
 
}
 
 
 
/**
 
* 组织方式:使命是启动服务器,等待客户端持续
 
*/
 
public CSServer() {
 
try {
 
server = new ServerSocket(PORT);
 
mExecutors = Executors.newCachedThreadPool(); // 建立线程池
 
System.out.println("服务器已启动,等待客户端持续...");
 
Socket client = null;
 
/*
 
* 用死轮回等待多个客户端的持续,持续一个就启动一个线程举行经管
 
*/
 
while (true) {
 
client = server.accept();
 
// 把客户端放入鸠合中
 
mClientList.add(client);
 
mExecutors.execute(new Service(client)); // 启动一个线程,用以等待从客户端发来的消息
 
}
 
} catch (Exception e) {
 
e.printStackTrace();
 
}
 
}
 
 
 
class Service implements Runnable {
 
private Socket socket;
 
private BufferedReader in = null;
 
private String message = "";
 
 
 
public Service(Socket socket) {
 
this.socket = socket;
 
try {
 
in = new BufferedReader(new InputStreamReader(
 
socket.getInputStream()));// 获取输入流对象
 
// 客户端只要一连到服务器,便发送持续胜利的信息
 
message = "游戏开发运营服务器地点:" + this.socket.getInetAddress();
 
this.sendMessage(message);
 
message = "目前持续总数:" + mClientList.size();
 
this.sendMessage(message);
 
} catch (IOException e) {
 
e.printStackTrace();
 
}
 
 
 
}
 
 
 
@Override
 
public void run() {
 
try {
 
while (true) {
 
if ((message = in.readLine()) != null) {
 
// 当客户端发送的信息为:exit时,封闭持续
 
if (message.equals("exit")) {
 
closeSocket();
 
break;
 
} else {
 
// 汲取客户端发过来的信息message,而后转发给客户端。
 
message = socket.getInetAddress() + ":" + message;
 
this.sendMessage(message);
 
}
 
}
 
}
 
} catch (Exception e) {
 
e.printStackTrace();
 
}
 
}
 
 
 
/**
 
* 封闭客户端
 
 
* @throws IOException
 
*/
 
public void closeSocket() throws IOException {
 
mClientList.remove(socket);
 
in.close();
 
message = "主机:" + socket.getInetAddress() + "封闭持续\r目前在线:"
 
+ mClientList.size();
 
socket.close();
 
this.sendMessage(message);
 
}
 
 
 
/**
 
* 将常州手游开发汲取的消息转发给每一个客户端
 
 
* @param msg
 
*/
 
 
 
public void sendMessage(String msg) {
 
System.out.println(msg);// 先在控制台输出
 
int count = mClientList.size();
 
// 遍历客户端鸠合
 
for (int i = 0; i < count; i++) {
 
Socket mSocket = mClientList.get(i);
 
PrintWriter out = null;
 
try {
 
out = new PrintWriter(new BufferedWriter(
 
new OutputStreamWriter(mSocket.getOutputStream())),
 
true);// 建立输出流对象
 
out.println(msg);// 转发
 
} catch (IOException e) {
 
e.printStackTrace();
 
}
 
}
 
}
 
}
 
 
 
}
 
 
 
二、Android客户端
 
思路:
 
 
 
设置权限。
 
 
 
首先开发线程,在线程中持续服务器,并获取输入流和输出流,并用一个死轮回汲取来自服务器的消息,输入流收到消息举行处分,用handler关照给UI线程更新文本框。
 
 
 
编纂框填好消息,干脆点击发送。用获取的输出流发送消息。
 
 
 
代码:
 
 
 
/**
 
 * Android Tcp即时通信客户端
 
 */
 
public class MainActivity extends Activity implements Runnable{
 
    private TextView tv_msg = null;
 
    private EditText ed_msg = null;
 
    private Button btn_send = null;
 
    private static final String HOST = "192.168.0.100";//服务器地点
 
    private static final int PORT = 8888;//持续端口号
 
    private Socket socket = null;
 
    private BufferedReader in = null;
 
    private PrintWriter out = null;
 
 
 
    //汲取线程发送过来信息,并用TextView追加表现
 
    public Handler mHandler = new Handler() {
 
        public void handleMessage(Message msg) {
 
            super.handleMessage(msg);
 
            tv_msg.append((CharSequence) msg.obj);
 
        }
 
    };
 
 
 
    @Override
 
    public void onCreate(Bundle savedInstanceState) {
 
        super.onCreate(savedInstanceState);
 
        setContentView(R.layout.activity_main);
 
 
 
        tv_msg = (TextView) findViewById(R.id.txt_1);
 
        ed_msg = (EditText) findViewById(R.id.et_talk);
 
        btn_send = (Button) findViewById(R.id.btn_send);
 
 
 
        btn_send.setOnClickListener(new Button.OnClickListener() {
 
 
 
            @Override
 
            public void onClick(View v) {
 
                String msg = ed_msg.getText().toString();
 
                if (socket.isConnected()) {//要是服务器持续
 
                    if (!socket.isOutputShutdown()) {//要是输出流没有断开
 
                        out.println(msg);//点击按钮发送消息
 
                        ed_msg.setText("");//清空编纂框
 
                    }
 
                }
 
            }
 
        });
 
        //启动常州游戏开发培训线程,持续服务器,并用死轮回等待,汲取服务器发送过来的数据
 
        new Thread(this).start();
 
    }
 
 
 
    /**
 
     * 持续服务器
 
     */
 
    private void connection() {
 
        try {
 
            socket = new Socket(HOST, PORT);//持续服务器
 
            in = new BufferedReader(new InputStreamReader(socket
 
                    .getInputStream()));//汲取消息的流对象
 
            out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
 
                    socket.getOutputStream())), true);//发送消息的流对象
 
        } catch (IOException ex) {
 
            ex.printStackTrace();
 
            ShowDialog("持续服务器失利:" + ex.getMessage());
 
        }
 
    }
 
 
 
    /**
 
     * 要是持续出现异常,弹出AlertDialog!
 
     */
 
    public void ShowDialog(String msg) {
 
        new AlertDialog.Builder(this).setTitle("关照").setMessage(msg)
 
                .setPositiveButton("ok", new DialogInterface.OnClickListener() {
 
 
 
                    @Override
 
                    public void onClick(DialogInterface dialog, int which) {
 
 
 
                    }
 
                }).show();
 
    }
 
 
 
    /**
 
     * 读取服务器发来的信息,并通过Handler发给UI线程
 
     */
 
    public void run() {
 
        connection();// 持续到服务器
 
        try {
 
            while (true) {//死轮回保卫,监控服务器发来的消息
 
                if (!socket.isClosed()) {//要是服务器没相封闭
 
                    if (socket.isConnected()) {//持续平常
 
                        if (!socket.isInputShutdown()) {//要是输入流没有断开
 
                            String getLine;
 
                            if ((getLine = in.readLine()) != null) {//读取汲取的信息
 
                                getLine += "\r";
 
                                Message message=new Message();
 
                                message.obj=getLine;
 
                                mHandler.sendMessage(message);//关照UI更新
 
                            } else {
 
 
 
                            }
 
                        }
 
                    }
 
                }
 
            }
 
        } catch (Exception e) {
 
            e.printStackTrace();
 
        }
 
    }
 
 
 
}
 
 
 
 
 
运行效果:
 
 
 
 
 
 
要是要扩大优化成一个有模有样的即时通信对象。思量发发送的消息用json举行格式化,包括用户昵称和图片地点等等,服务器收到后分析,在增加上光阴等举行从新包装。客户端收到消息,一样举行分析,装载到粉饰好的listview中间。
 

上篇:上一篇:安卓线程handler用法
下篇:下一篇:Android 一套完备的 Socket 办理计划