12、android socket使用demo:网络聊天
目录:
一、效果图
二、原代码分享
三、代码分析
四、总结
一、效果图如下:
客户端1: 客户端2:

二、原代码分享如下:
1、java代码只有一个
MainActivity.java
package com; import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList; import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.TextView; import com.example.androidsockettest.R; public class MainActivity extends Activity{ private Button button_send = null;
private EditText et_ip = null;
private EditText et_port = null;
private EditText et_conent = null;
private TextView tv_history = null;
private CheckBox checkBoxSwitch = null;
private static int defaultPort = 8888;
public static ArrayList<Socket> socketList=new ArrayList<Socket>(); private OutputStream out=null;
private Handler handler = null;
private Socket s = null;
String tag = "chatRoom";
private BufferedReader buRead = null; private final int UPDATE_HISTORY_CONTENT = 0;
private final int UPDATE_INPUT_CONTENT = 1; @Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity); init(); configure(); serverStart();
} @Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
} public void init()
{
button_send = (Button)findViewById(R.id.button_send);
et_ip = (EditText)findViewById(R.id.editText_ip);
et_port = (EditText)findViewById(R.id.EditText_port);
et_conent = (EditText)findViewById(R.id.EditText_content);
tv_history = (TextView)findViewById(R.id.textView_history_content);
checkBoxSwitch = (CheckBox)findViewById(R.id.checkBox_server_start);
} public void configure()
{
button_send.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
// TODO Auto-generated method stub
try {
String content = et_conent.getText().toString();//读取用户输入文本 if(out == null)
{
CommonUtils.LogWuwei(tag,"the fucking out is null");
return;
} out.write((content+"\n").getBytes("utf-8"));//写入socket String history_content = tv_history.getText().toString();
history_content+="你说:"+et_conent.getText()+"\n"; Message msg = new Message();
msg.what = UPDATE_HISTORY_CONTENT;
msg.obj = history_content;
handler.sendMessage(msg); msg = new Message();
msg.what = UPDATE_INPUT_CONTENT;
msg.obj = "";
handler.sendMessage(msg); CommonUtils.LogWuwei(tag, "send success");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
CommonUtils.LogWuwei(tag, "send failed "+e.getMessage());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
CommonUtils.LogWuwei(tag, "send failed "+e.getMessage());
}
}
}); checkBoxSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// TODO Auto-generated method stub
if(isChecked)
{
CommonUtils.LogWuwei(tag, "clientStart");
clientStart();
}
else
{
CommonUtils.LogWuwei(tag, "clientStop");
clientStop();
}
}
}); handler = new Handler()
{
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
switch (msg.what)
{
case UPDATE_HISTORY_CONTENT:
CommonUtils.LogWuwei(tag, "更新历史记录"+msg.obj);
tv_history.setText((String)msg.obj);
break; case UPDATE_INPUT_CONTENT:
CommonUtils.LogWuwei(tag, "清空输入记录");
et_conent.setText("");//清空文本
break;
}
}
}; } public void serverStart()
{
try { final ServerSocket ss = new ServerSocket(defaultPort); CommonUtils.LogWuwei(tag, "on serverStart"); new Thread()
{
public void run()
{
while(true)
{
try {
CommonUtils.LogWuwei(tag, "on serverStart: ready to accept");
s=ss.accept();
socketList.add(s);
buRead = new BufferedReader(new InputStreamReader(s.getInputStream(), "utf-8")); String receive_content = null;
while ((receive_content=readFromClient())!=null) {
CommonUtils.LogWuwei(tag,"客户端说:"+receive_content); String history_content = tv_history.getText().toString();
history_content+=s.getInetAddress()+"说:"+receive_content+"\n"; Message msg = new Message();
msg.what = UPDATE_HISTORY_CONTENT;
msg.obj = history_content;
handler.sendMessage(msg); for (Socket ss:socketList)
{
OutputStream out=ss.getOutputStream();
out.write(("[服务器已经收到消息]"+"\n").getBytes("utf-8"));
}
} } catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
}
}.start(); } catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } private String readFromClient(){
try {
return buRead.readLine();
} catch (Exception e) {
//删除此Socket
socketList.remove(s);
}
return null;
} public void clientStart()
{
new Thread(new Runnable() { @Override
public void run() {
try {
String ip = et_ip.getText().toString();
String port = et_port.getText().toString(); if(!port.equals("") && port != null)
{
s=new Socket(ip, defaultPort);
}
else
{
s=new Socket(ip, Integer.parseInt(port));
} out=s.getOutputStream();
CommonUtils.LogWuwei(tag, "clientStart success"); } catch (IOException e) {
e.printStackTrace();
CommonUtils.LogWuwei(tag, "clientStart failed "+e.getMessage());
}
}
}).start(); } public void clientStop()
{
try {
if(s != null)
s.close();
if(out != null)
out.close(); } catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } }
2、xml文件也是只有一个
main_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" > <EditText
android:id="@+id/editText_ip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/TextView_ip_tips"
android:layout_marginRight="15dp"
android:text="192.168.1.232"
android:ems="10"/> <TextView
android:id="@+id/TextView_ip_tips"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginTop="16dp"
android:text="接受IP:" /> <EditText
android:id="@+id/EditText_port"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/textView_port_tips"
android:layout_below="@+id/editText_ip"
android:layout_marginTop="16dp"
android:ems="10"
android:text="8888"
android:inputType="number" > <requestFocus />
</EditText> <TextView
android:id="@+id/textView_port_tips"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/EditText_port"
android:layout_alignParentLeft="true"
android:text="输入端口号:" /> <TextView
android:id="@+id/textView_history_content"
android:layout_width="match_parent"
android:layout_height="350dp"
android:layout_below="@+id/checkBox_server_start" /> <Button
android:id="@+id/button_send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/EditText_content"
android:layout_alignParentBottom="true"
android:text="发送" /> <EditText
android:id="@+id/EditText_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
android:ems="10" /> <CheckBox
android:id="@+id/checkBox_server_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/EditText_port"
android:layout_marginLeft="24dp"
android:checked="false"
android:text="开启发送模式" /> </RelativeLayout>
三、代码分析
流程分析:
1、服务端
程序开启的时候,执行serverStart()方法,将自身做为serverSocket,端口号为8888,做为socket的服务器跑起来;
在循环中,通过带有阻塞特性的accept函数等待连接,如果有连接,通过accept函数得到套接字s,然后通过s的getInputStream()方法得到输入流(也就是对方发送的内容),同事也从s的getInetAddress方法得到对方的ip地址;这样一来就读到了两个重要信息 ① ip地址 ②发送过来的内容
2、客户端
在通过设置edittext内容,配置得到对方的IP地址和端口号,如果选中"开启发送模式",然后创建套件字s,通过套接字的getOutputStream()方法得到可写流out;
“发送”按钮的回调函数是用来通过可写流-写入-套接字(写入内容为用户输入的文本)
这样一来,程序基本ok了,然后运行在两部手机上,即可实现基于socket的网络聊天。
四、总结
参考连接:
1、 http://mobile.51cto.com/android-386691.htm
2、http://blog.csdn.net/conowen/article/details/7313671
3、http://www.cnblogs.com/harrisonpc/archive/2011/03/31/2001565.html
socket简单通信的几个关键点:
1、如果要实现接受消息功能,需要本身做为服务端跑起来,同时得到可读流。关键点:serverSocket、getIputStream
2、如果要实现消息发送功能,需要本身创建套接字,并得到可写流,同时设置要发送到的ip和端口号。关键点:socket、getOutputStream、对方IP、对方Port
That's All
没找到在随笔里如何添加附件,工程附件大家去网盘下载去吧。http://pan.baidu.com/s/1o6vA8sU
12、android socket使用demo:网络聊天的更多相关文章
- 使用socket搭建一个网络聊天室
#服务器端import socket import threading #创建一个TCP端 sock = socket.socket(socket.AF_INET, socket.SOCK_STREA ...
- Android应用开发基础篇(12)-----Socket通信
链接地址:http://www.cnblogs.com/lknlfy/archive/2012/03/03/2378669.html 一.概述 网络通信无论在手机还是其他设备上都应用得非常广泛,因此掌 ...
- Android应用开发基础篇(12)-----Socket通信(转载)
转自:http://www.devdiv.com/android_socket_-blog-258060-10594.html 一.概述 网络通信无论在手机还是其他设备上都应用得非常广泛,因此掌握网络 ...
- Java实现网络聊天中使用的socket API与Linux socket API之间的关系
尝试着用Java编写一个网络聊天程序,发现总不如网上写的好,所以就直接引用了网上大神的优秀代码.代码如下: package project1; import java.awt.*; import ja ...
- 基于Android Classic Bluetooth的蓝牙聊天软件
代码地址如下:http://www.demodashi.com/demo/12133.html BluetoothChat 基于Android Classic Bluetooth的蓝牙聊天软件,目前仅 ...
- Android - 传统蓝牙通信聊天
Android -传统蓝牙通信聊天 技术:java+Android4.4+jdk1.8 运行环境:Android4.4.Android7.0 概述 Android 传统蓝牙的使用,包括开关蓝牙.搜索设 ...
- Netty网络聊天(一) 聊天室实战
首发地址; Netty网络聊天(一) 聊天室实战 之前做过一个IM的项目,里面涉及了基本的聊天功能,所以注意这系列的文章不是练习,不含基础和逐步学习的部分,直接开始实战和思想引导,基础部分需要额外的去 ...
- Android Socket
Android Socket 参考资料 菜鸟教程 怎么理解TCP的面向连接和UDP的无连接 https://www.cnblogs.com/xiaomayizoe/p/5258754.html htt ...
- Android Socket通信详解
一.Socket通信简介 Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客 ...
随机推荐
- .NET中的访问修饰符
.NET中一共有五种访问修饰符 分别是 public 公共的,访问权限最高的. private ...
- C#中如何将combox中的下拉项和一个枚举中的各项进行绑定
实现一个combobox,将其各个下拉项与枚举进行绑定 效果图如下: 代码详解如下: 枚举: public enum StoreSite { /// <summary> /// 未知 // ...
- partial class 说明
C# 2.0 可以将类.结构或接口的定义拆分到两个或多个源文件中,在类声明前添加partial关键字即可. 例如:下面的PartialTest类 class PartialTest { string ...
- Redis监控方案
Redis 监控最直接的方法当然就是使用系统提供的 info 命令来做了,你只需要执行下面一条命令,就能获得 Redis 系统的状态报告. redis-cli info 内存使用 如果 Redis 使 ...
- STM32F0xx_TIM基本延时配置详细过程
前言 关于定时器大家都应该不会陌生,因为处理器都有这个功能.今天总结的F0系列芯片的定时器根据芯片型号不同,数量也不同.定时器分类:基本定时器.通用定时器和高级定时器.计数位数也有不同,有16位的,有 ...
- python的http请求应用--每日签到
写点python吧,python其实是个很好用的工具,作为浇水语言,跟其他语言联系也很紧密,想用什么包直接import,导入ctypes调用底层函数库,导入web相关的包可以轻松写爬虫,今天我们写的跟 ...
- Python学习教程(learning Python)--1.3 Python数据输入
多数应用程序都有数据输入语句,用于读入数据,和用户进行交互,在Python语言里,可以通过raw_input函数实现数据的从键盘读入数据操作. 基本语法结构:raw_input(prompt) 通常p ...
- sql server 判断是否存在数据库,表,列,视图
1 判断数据库是否存在if exists (select * from sys.databases where name = '数据库名') drop database [数据库名] 2 判断表 ...
- ociuldr 支持分多个数据文件
在审计工作,将几亿条的oracle数据通过sqlserver自带工具导入到sqlserver中,速度不是特别的理想,虽然通过视图方式能提高一些速度,但是既不简洁,也不方便. 用ociuldr工具,可以 ...
- hdu 2141 Can you find it?
题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=2141 Can you find it? Description Give you three sequ ...