目录:

一、效果图

二、原代码分享

三、代码分析

四、总结

一、效果图如下

客户端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:网络聊天的更多相关文章

  1. 使用socket搭建一个网络聊天室

    #服务器端import socket import threading #创建一个TCP端 sock = socket.socket(socket.AF_INET, socket.SOCK_STREA ...

  2. Android应用开发基础篇(12)-----Socket通信

    链接地址:http://www.cnblogs.com/lknlfy/archive/2012/03/03/2378669.html 一.概述 网络通信无论在手机还是其他设备上都应用得非常广泛,因此掌 ...

  3. Android应用开发基础篇(12)-----Socket通信(转载)

    转自:http://www.devdiv.com/android_socket_-blog-258060-10594.html 一.概述 网络通信无论在手机还是其他设备上都应用得非常广泛,因此掌握网络 ...

  4. Java实现网络聊天中使用的socket API与Linux socket API之间的关系

    尝试着用Java编写一个网络聊天程序,发现总不如网上写的好,所以就直接引用了网上大神的优秀代码.代码如下: package project1; import java.awt.*; import ja ...

  5. 基于Android Classic Bluetooth的蓝牙聊天软件

    代码地址如下:http://www.demodashi.com/demo/12133.html BluetoothChat 基于Android Classic Bluetooth的蓝牙聊天软件,目前仅 ...

  6. Android - 传统蓝牙通信聊天

    Android -传统蓝牙通信聊天 技术:java+Android4.4+jdk1.8 运行环境:Android4.4.Android7.0 概述 Android 传统蓝牙的使用,包括开关蓝牙.搜索设 ...

  7. Netty网络聊天(一) 聊天室实战

    首发地址; Netty网络聊天(一) 聊天室实战 之前做过一个IM的项目,里面涉及了基本的聊天功能,所以注意这系列的文章不是练习,不含基础和逐步学习的部分,直接开始实战和思想引导,基础部分需要额外的去 ...

  8. Android Socket

    Android Socket 参考资料 菜鸟教程 怎么理解TCP的面向连接和UDP的无连接 https://www.cnblogs.com/xiaomayizoe/p/5258754.html htt ...

  9. Android Socket通信详解

    一.Socket通信简介  Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客 ...

随机推荐

  1. php实现文件上传的源码

    php实现文件上传的源码,更多php技术开发就去php教程网,http://php.662p.com <?php ##author :Androidyue ##sina @androidyue ...

  2. centos下网络的基本配置方法讲解

    上一篇中我们已经成功安装了我们的centos系统,但是我们可能发现我们安装的centos上不了网,所以这一章我们来说说如何配置centos来连接外网和局域网. 我们首先来认识一下linux下部分网络配 ...

  3. java项目编译有误

    classpath component

  4. POJ C++程序设计 编程题#2 魔兽世界之二:装备

    编程题#2: 魔兽世界之二:装备 来源: POJ (Coursera声明:在POJ上完成的习题将不会计入Coursera的最后成绩.) 注意: 总时间限制: 1000ms 内存限制: 65536kB ...

  5. CentOS编译安装lamp

    LAMP环境搭建(编译安装CentOS+httpd2.2+mysql5.5+php5.4) 首先准备以下压缩包 <ignore_js_op> (1)编译安装apache 1.配置防火墙,开 ...

  6. 错记-checkbox radio

    很多时候我想会用到浏览器默认的单选按钮或者复选框,比如说偷懒的时候或者心情不好的时候╮(╯﹏╰)╭, 在html结构里我想实现点击文字旁边的单选按钮就跟着选中或反之,像这样:

  7. 代码分享:php对二维数组进行排序

    发布:net/PHP编程  编辑:thebaby   2013-06-28 13:12:54  [大 中 小] 转自:http://www.jbxue.com/article/9991.html本文介 ...

  8. 2)Java中的==和equals

    Java中的==和equals   1.如果比较对象是值变量:只用==   2.如果比较对象是引用型变量:      ==:比较两个引用是不是指向同一个对象实例.      equals:       ...

  9. android ping网络是否成功

    public static boolean pingHost(String str) { //str 为要ping的IP地址 boolean result = false; try { Process ...

  10. 使用 Attribute +反射 来对两个类之间动态赋值

    看同事使用的 一个ORM 框架 中 有这样一个功能  通过特性(附加属性)的功能来 实现的两个类对象之间动态赋值的 功能 觉得这个功能不错,但是同事使用的 ORM 并不是我使用的  Dapper  所 ...