Android 聊天室的开发
来源:互联网 发布:mysql主键是主键长度 编辑:程序博客网 时间:2024/05/21 22:48
刚开始接触Android的网络通信开发。
目前自己写了一个聊天室的小程序,记录一下。
本程序包括:
1.服务器:由java开发
2.客户端:由Android开发
首先贴上演示效果。先开启服务端程序以后,再打开客户端。
服务器的console起到接受并且转发的目的:
服务端代码:
package com.ustclin.talk;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;import java.util.ArrayList;public class Server { //private static final String IP_ADDRESS = "192.168.0.200"; private static final int PORT = 18888; private static int num = 0; public static ArrayList<Socket> socketList = new ArrayList<Socket>(); /** * @param args */ public static void main(String[] args) { ServerSocket serverSocket = null; System.out.println("ServerSocket Begin........"); try { serverSocket = new ServerSocket(PORT); // 使用循环方式一直等待客户端的连接 while (true) { num++; Socket accept = serverSocket.accept(); socketList.add(accept); System.out.println("arrayList num = "+socketList.size()); // 启动一个新的线程,接管与当前客户端的交互会话 new Thread(new ServerThread(accept , "Client "+num ), "Client " + num).start(); } } catch (IOException e) { e.printStackTrace(); } finally { try { serverSocket.close(); System.out.println("----> serverSocket closed."); } catch (IOException e) { e.printStackTrace(); } } }}/** * @author JCC 服务器处理客户端会话的线程 */class ServerThread implements Runnable { Socket socket = null; String clientName = null; public ServerThread(Socket socket , String clientName) { System.out.println("Create a new ServerThread..."); this.socket = socket; this.clientName = clientName; } @Override public void run() { try { // 接收客户端消息 BufferedReader in = new BufferedReader(new InputStreamReader( socket.getInputStream())); while (true) { String message = null; if (!socket.isClosed()) { try { message = in.readLine(); } catch (Exception e) { e.printStackTrace(); } if(null == message){ // the socket is null , means that the client is disconnect Server.socketList.remove(socket); break; } System.out.println("server read Line from "+ clientName + " success! message = " + message); for(Socket ss : Server.socketList){ // 发送消息,向客户端 PrintWriter out = new PrintWriter(new BufferedWriter( new OutputStreamWriter(ss.getOutputStream())), true); out.println(this.clientName +": "+ message); System.out.println("Thread " + clientName + " socket send out"); } } } } catch (IOException e) { e.printStackTrace(); } finally { System.out.println("out of while"); } }}interface Constant { public static final String SERVER_IP = "192.168.0.200"; public static final int PORT = 19999;}
客户端主程序:
package com.ustc.linkun.chat;import android.content.Context;import android.os.Bundle;import android.os.Handler;import android.os.Looper;import android.os.Message;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;import java.io.BufferedReader;import java.io.BufferedWriter;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 implements View.OnClickListener{ private static final String TAG = "ConnectToServer"; private static final String CONNECTED = "connected ! "; private static final String CONNECTINGSERVER = "connecting ..."; private TextView tvForIpAddress; private TextView tvForPort; private EditText mIpAddress; private EditText mPort; private Button mConnect; private TextView mServerMsg; private EditText editText; private Button button1; private static final int SEND_DATA = 0; private static final int GET_DATA_FROM_SERVER = 1; private static final int CONNECT_TO_SERVER = 2; private static final int CONNECTING = 3; private MyHandler myHandler; private Socket socket = null; private Context mContext; /** * Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mContext = this; tvForIpAddress = (TextView) findViewById(R.id.tvForIpAddress); tvForPort = (TextView) findViewById(R.id.tvForPort); mIpAddress = (EditText)findViewById(R.id.ipAddress); mPort = (EditText) findViewById(R.id.port); mConnect = (Button) findViewById(R.id.connect); editText = (EditText) findViewById(R.id.editText1); mServerMsg = (TextView) findViewById(R.id.serverMsg); //mServerMsg.setEnabled(false); button1 = (Button) findViewById(R.id.button1); myHandler = new MyHandler(); mConnect.setOnClickListener(this); button1.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()){ // connect server case R.id.connect: // connecting , avoid multi button click which can result sending multi-connect request Runnable r0 = new Runnable() { @Override public void run() { Message msg = myHandler.obtainMessage(); msg.what = CONNECTING; myHandler.sendMessage(msg); } }; new Thread(r0).start(); // use for connection Runnable r1 = new Runnable() { @Override public void run() { initSocket(); ClientThread ct = new ClientThread(socket , "Client"); new Thread(ct).start(); //connectToServer(mIpAddress.getText().toString(), Integer.parseInt(mPort.getText().toString())); if(socket.isConnected()){ Message msg = myHandler.obtainMessage(); msg.what = CONNECT_TO_SERVER; myHandler.sendMessage(msg); } } }; new Thread(r1).start(); break; // send data case R.id.button1: Runnable r2 = new Runnable() { @Override public void run() { Message msg = myHandler.obtainMessage(); String str = editText.getText().toString(); System.out.println(">>>>editText: " +str); Bundle bundle = new Bundle(); bundle.putString("content", str); msg.what = SEND_DATA; msg.setData(bundle); myHandler.sendMessage(msg); } }; new Thread(r2).start(); break; default: break; } } private void initSocket() { try{ //socket = new Socket(ipAddress , port); socket = new Socket(mIpAddress.getText().toString(),Integer.parseInt(mPort.getText().toString())); socket.setKeepAlive(true); socket.setSoTimeout(10 * 60 * 1000); } catch (Exception e){ e.printStackTrace(); } } //private class private class MyHandler extends Handler { public MyHandler() { } public MyHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what){ case SEND_DATA: //Bundle bundle = new Bundle(); final String str = (String)msg.getData().get("content"); System.out.println(">>>>>content : " + str); if(str.equals("")){ Toast.makeText(mContext,"不能发送空内容!",Toast.LENGTH_SHORT).show(); } else { new Thread(new Runnable() { @Override public void run() { sendData(str); } }).start(); editText.setText(""); //mServerMsg.append(str); } break; case GET_DATA_FROM_SERVER: String str1 = (String) msg.getData().get("content"); System.out.println("myHandler get str = " + str1); mServerMsg.append("\n"+str1); case CONNECT_TO_SERVER: mIpAddress.setEnabled(false); mPort.setEnabled(false); mConnect.setText(CONNECTED); tvForIpAddress.setVisibility(View.GONE); tvForPort.setVisibility(View.GONE); mIpAddress.setVisibility(View.GONE); mPort.setVisibility(View.GONE); mConnect.setVisibility(View.GONE); //mServerMsg.setText("The Server is connected!"); case CONNECTING: mConnect.setText(CONNECTINGSERVER); mConnect.setEnabled(false); default: break; } } } // send data private void sendData(String content) { // server is on try { //String content = editText.getText().toString(); PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter (socket.getOutputStream())), true); //发送数据 out.println(content); System.out.println(">>>>>send out SUCCESSFUL!"); } catch (Exception e) { e.printStackTrace(); } } // private void send_CONNECTION_CLOSE_DATA(){ try { PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter (socket.getOutputStream())), true); //发送数据 out.println("closing-connection"); System.out.println("closing-connection"); } catch (Exception e){ e.printStackTrace(); } } // close the connection to the server @Override protected void onDestroy() { super.onDestroy(); try { if (null != socket) { new Thread(new Runnable() { @Override public void run() { send_CONNECTION_CLOSE_DATA(); } }); socket.close(); } } catch (IOException e) { e.printStackTrace(); } } private class ClientThread implements Runnable{ private Socket socket = null; private String name; public ClientThread(Socket socket , String threadName){ this.socket = socket; this.name = threadName; } @Override public void run() { try { // 接收客户端消息 BufferedReader in = new BufferedReader(new InputStreamReader( socket.getInputStream())); while (true) { String message = null; try { if (!socket.isClosed()) { message = in.readLine(); System.out.println("Server:" + message); Message msg = myHandler.obtainMessage(); Bundle b = new Bundle(); b.putString("content" , message); msg.setData(b); msg.what = GET_DATA_FROM_SERVER; myHandler.sendMessage(msg); System.out.println("read Line success! message = " + message); } Thread.sleep(1000); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } //in = socket.getInputStream(); } catch (IOException e) { e.printStackTrace(); } } }}
客户端界面布局:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/tvForIpAddress" android:text="IP Address: " /> <EditText android:id="@+id/ipAddress" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="input the ip address here" android:text="192.168.0.200"> </EditText> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/tvForPort" android:text="port: " /> <EditText android:id="@+id/port" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="input the port number here" android:text="18888"> </EditText> <Button android:id="@+id/connect" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="connect"> </Button> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center" android:text="----Talk----" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/serverMsg" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="This is for TALK History zone" /> </RelativeLayout> <EditText android:id="@+id/editText1" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint=""> </EditText> <Button android:id="@+id/button1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="send"> </Button></LinearLayout>
先运行Server.java , 保证服务器在客户端之前开启
客户端是用Android Studio开发的,可以直接导入。如果你的IDE是ADT,
则可以选择性得添加里边的MainActivity.java 和 main.xml布局文件。需要
注意的是,AndroidManifest.xml文件需要添加访问INTERNET的权限运行多个客户端,配置好服务器的IP地址后,即可进行聊天。
具体的源码大家可以去看看:基于socket的Android聊天程序
0 0
- Android 聊天室的开发
- 【聊天室】android 简单的聊天室
- Android开发之聊天室
- Android基于XMPP Smack openfire 开发的聊天室(一)【会议服务、聊天室列表、加入】
- Android基于XMPP Smack openfire 开发的聊天室(一)【会议服务、聊天室列表、加入】
- Android基于XMPP Smack openfire 开发的聊天室(一)【会议服务、聊天室列表、加入】
- Android基于XMPP Smack openfire 开发的聊天室(一)【会议服务、聊天室列表、加入】
- Android基于XMPP Smack openfire 开发的聊天室(一)【会议服务、聊天室列表、加入】
- android开发一个聊天室client
- Android基于XMPP Smack openfire 开发的聊天室
- Android基于XMPP Smack openfire 开发的聊天室(一)
- Android基于XMPP Smack openfire 开发的聊天室
- Android基于XMPP Smack openfire 开发的聊天室
- Android基于XMPP Smack openfire 开发的聊天室(一)
- 网页的视频聊天室开发
- 网页聊天室的开发笔记
- 基于JAVA的聊天室开发
- go开发的web聊天室
- MySQL小型高可用架构(组合)
- 线性索引查找
- 模板函数及一些代码规范
- MySQL查询对NULL的处理
- ubuntu 12.04设置开机启动图形应用程序,替换默认图形桌面
- Android 聊天室的开发
- 安卓开发 捕获异常并重启app
- char与varchar的区别
- tsiLdekniLoteerTyraniBnettalF.114
- Linux系列软件源码安装之五-----vsftpd服务器
- Mysql + keepalived 实现双主热备读写分离
- UINavigationController返回手势失效问题
- MyBatis映射错误:There is no setter for property named xxx
- 使用ASIHTTPRequest的ASIDataCompressor与ASIDataDecompressor进行gzip压缩与解压缩,出现的问题