Android聊天室
来源:互联网 发布:wtaps15aw军裤数据 编辑:程序博客网 时间:2024/06/09 21:20
背景
最新在研究网络编程,感觉好好玩,然后玩得兴起就想做个聊天室来玩玩。这个聊天室叫 ChatRoom ,是一个基于 TCP 通信的聊天室,并且用到了一些 Material Design 的控件,之前一直都在赶项目都没时间学习 Material Design(其实不是没时间,是有些事情很烦,所以耽搁了),工作室的昭哥老说我,你基础工不扎实,嘿嘿。
基础
我们来围观李俊师兄写的 TCP:java 网络编程 TCP协议
李俊师兄写的很详细,我也来班门弄斧下(^0^):
TCP 是一种可靠、必须连接才能通信的协议。因为需要连接才能通信,所以 TCP 通信严格区分客户端和服务器端,只有客户端连接了服务器端才能实现通信,服务器端不能连接客户端并且需要事先启动,等待客户端的请求。
ChatRoom
好了,扯了辣么多,我们来看看 ChatRoom 是怎么实现的吧!先看看效果:
服务器端
/** * Created by kn on 2016/5/24. * * 聊天室主线程服务 */public class MyServerSocket { public static void main(String args[]){ new ServerListener().start(); }}/** * Created by kn on 2016/5/24. * * 聊天监听线程类 */public class ServerListener extends Thread { @Override public void run() { try { //端口号port:1~65535 ServerSocket serverSocket = new ServerSocket(30000); while(true){ //该方法会阻塞当前线程 Socket socket = serverSocket.accept(); //建立连接 System.out.println("有客户端链接到本地的30000端口"); //将socket传递给新的线程 ChatSocket chatSocket = new ChatSocket(socket); chatSocket.start(); ChatManager.getInstance().add(chatSocket); } } catch (IOException e) { e.printStackTrace(); } }}/** * Created by kn on 2016/5/24. * * 聊天线程类 */public class ChatSocket extends Thread { Socket socket; public ChatSocket(Socket socket) { this.socket = socket; } @Override public void run() { try { BufferedReader br = new BufferedReader( new InputStreamReader(socket.getInputStream(), "UTF-8")); String line = null; while ((line = br.readLine()) != null) { ChatManager.getInstance().publish(this, line); } br.close(); } catch (IOException e) { e.printStackTrace(); } } /** * 输出服务器返回的信息 * @param message */ public void showMessage(String message) { try { socket.getOutputStream().write((message + "\n").getBytes("UTF-8")); } catch (IOException e) { e.printStackTrace(); } } /** * 判断socket是否关闭 * @return */ public boolean isSocketClosed(){ return socket.isClosed(); }}/** * Created by kn on 2016/5/24. * * 聊天室线程管理类 */public class ChatManager { private static ChatManager instance = new ChatManager(); //聊天线程列表 Vector<ChatSocket> vector = new Vector<>(); private ChatManager() { } /** * 单例模式 * @return */ public static ChatManager getInstance() { if (instance == null) { synchronized (ChatManager.class) { if (instance == null) { instance = new ChatManager(); } } } return instance; } /** * 添加聊天线程 * * @param chatSocket */ public void add(ChatSocket chatSocket) { vector.add(chatSocket); } /** * 向聊天室的其他线程发布消息 * @param chatSocket * @param message */ public void publish(ChatSocket chatSocket, String message) { //遍历线程列表 for (int i = 0; i < vector.size(); i++) { ChatSocket mChatSocket = vector.get(i); //判断是否是己线程 if (!chatSocket.equals(mChatSocket)) { //判断该线程是否已经断开服务器的连接 if (mChatSocket.isSocketClosed()) { vector.remove(i); } else { mChatSocket.showMessage(message); } } } }}
写完以上代码,服务器端基本上完成了,其实现在,我们就可以玩聊天室了。打开多个 cmd 并输入 telnet localhost 30000 就可以连接服务器,然后你就可以在黑框下聊天了。
客户端
主界面,输入服务器的 IP 和聊天中显示的名字
public class MainActivity extends AppCompatActivity { MaterialEditText metName;//聊天的昵称 MaterialEditText metIP;//聊天室的IP ImageView ivAvatar;//聊天的头像 ButtonFlat btnEnter;//进入聊天按钮 ProgressBar progressBar;//进度条 FrameLayout flProgressBar; public static Socket socket = null; final static int SUCCESS = 0x01;//进入聊天室成功 final static int FAILURE = 0x02;//进入聊天室失败 final static int TIMEOUT = 0x03;//连接超时 final static int UN_KNOWN_HOST = 0x04;//未知主机 private BufferedWriter writer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView() { metName = (MaterialEditText) findViewById(R.id.met_name); metIP = (MaterialEditText) findViewById(R.id.met_ip); ivAvatar = (ImageView) findViewById(R.id.iv_avatar); btnEnter = (ButtonFlat) findViewById(R.id.btn_enter); progressBar = (ProgressBar) findViewById(R.id.progress); flProgressBar = (FrameLayout) findViewById(R.id.fl_progress); metName.setText("kntryer"); metIP.setText("192.168.1.101"); btnEnter.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { enterChatRoom(); } }); } private void enterChatRoom() { //获取ip final String ipString = metIP.getText().toString().trim(); new Thread(new Runnable() { @Override public void run() { try { socket = new Socket(); socket.connect(new InetSocketAddress(ipString, 30000), 5000); writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); handler.sendEmptyMessage(SUCCESS); } catch (SocketTimeoutException e) { //连接超时 在UI界面显示消息 handler.sendEmptyMessage(TIMEOUT); e.printStackTrace(); } catch (UnknownHostException e) { handler.sendEmptyMessage(UN_KNOWN_HOST); e.printStackTrace(); } catch (IOException e) { handler.sendEmptyMessage(FAILURE); e.printStackTrace(); } } }).start(); } Handler handler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { switch (msg.what) { case SUCCESS: String name = metName.getText().toString(); try { if (writer != null) { writer.write("system," + name + " enter ChatRoom\n"); writer.flush(); } } catch (IOException e) { e.printStackTrace(); } Intent intent = new Intent(MainActivity.this, ChatActivity.class); intent.putExtra("name", name); startActivity(intent); break; case FAILURE: showIsOpenWifi("Please check whether the network is open or not."); break; case TIMEOUT: showIsOpenWifi("SocketTimeoutException"); break; case UN_KNOWN_HOST: showIsOpenWifi("UnknownHostException"); break; } return false; } }); private void showIsOpenWifi(String message) { new SnackBar(this, message, "Yes", new View.OnClickListener() { @Override public void onClick(View v) { //跳到WiFi,这个还没做 } }).show(); }}
聊天界面
/** * Created by kn on 2016/5/24. */public class ChatActivity extends AppCompatActivity { ButtonFlat btnSent;//发送消息 MaterialEditText metMsg;//消息 ListView lvMsg;//显示消息 ArrayList<ChatMessage> msgList = new ArrayList<>();//消息列表 MessageAdapter adapter; Socket socket; String name;//聊天昵称 BufferedReader reader;//读取服务器返回的数据 BufferedWriter writer;//向服务器发送数据 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_chat); initView(); } private void initView() { name = getIntent().getStringExtra("name"); socket = MainActivity.socket; btnSent = (ButtonFlat) findViewById(R.id.btn_sent); metMsg = (MaterialEditText) findViewById(R.id.met_msg); lvMsg = (ListView) findViewById(R.id.lv_msg); adapter = new MessageAdapter(this,msgList); lvMsg.setAdapter(adapter); //开启一个新的线程监听聊天室,并获取聊天室的消息 getMessage(); btnSent.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ChatMessage chatMessage = new ChatMessage(); chatMessage.setType(2); chatMessage.setName(name); chatMessage.setMessage(metMsg.getText().toString()); msgList.add(chatMessage); adapter.notifyDataSetChanged(); String message = name + "," + metMsg.getText().toString(); metMsg.setText(""); setMessage(message); } }); } /** * 发送消息 * @param message */ private void setMessage(String message) { try { if (writer != null) { writer.write(message + "\n"); writer.flush(); } else { Toast.makeText(ChatActivity.this, "你已经离开 YY 聊天室!", Toast.LENGTH_LONG).show(); } } catch (IOException e) { e.printStackTrace(); } } /** * 获取聊天室的消息 */ private void getMessage() { new Thread(new Runnable() { @Override public void run() { try { writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); String line = null; while ((line = reader.readLine()) != null) { ChatMessage chatMessage = new ChatMessage(); String[] temp = line.split(","); System.out.print(temp[0]); if(temp[0].equals("system")){//如果temp[0]=system说明是系统消息 chatMessage.setType(0); chatMessage.setMessage(temp[1]); }else{ chatMessage.setType(1); chatMessage.setName(temp[0]); chatMessage.setMessage(temp[1]); } msgList.add(chatMessage); handler.sendEmptyMessage(0x00); } reader.close(); } catch (IOException e) { e.printStackTrace(); } } }).start(); } Handler handler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { adapter.notifyDataSetChanged(); return false; } });}
如何查看服务器 IP 呢?
打开 cmd ,输入 ipconfig ,就可以看到本机的 IP 设置,在无线局域网适配 wifi 这里的 IPv4地址 就是服务器的 IP 了。
模拟器可以连上服务器,手机却连不上怎么办?
网上说是手机是外网,访问不了内网的问题,手机和电脑连同一个 wifi 就行了。
0 0
- android聊天室
- Android聊天室
- 【聊天室】android 简单的聊天室
- android实现简单聊天室
- android 开放聊天室
- Android 群聊天室
- Android开发之聊天室
- android 聊天室窗口
- Android 聊天室的开发
- Android Socket 聊天室
- Android socket聊天室
- Android Socket之聊天室
- 蓝牙聊天室(Android版)
- Android 基于Socket的聊天室
- android开发一个聊天室client
- android 基于socket的聊天室
- Android 基于Socket的聊天室
- Android 基于Socket的聊天室
- 正则表达式
- 最进公共祖先(LCA)
- vertica-磁盘执行export出现insufficient space报错
- "undefined reference to" 问题解决方法
- 哈理工OJ—1013 Eqs(数学怪题)
- Android聊天室
- 第12周项目2-Time类中的运算符重载
- 《人生》续集
- TwoNote录音笔记的使用
- Session的一点理解
- 彻底解决delphi Indy10接收邮件汉字显示乱码的问题
- 关于大整数相乘
- 设计模式学习之路(二) ——观察者模式
- linux C select函数学习