网上很多基于Socket的聊天实现都是不完整的。。。

结合自己的经验给大家分享一下,完整代码可以在GitHub里获取https://github.com/zz7zz7zz/android-socket-client

1.废话不多说,附主要的Client类

package com.boyaa.push.lib.service;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketException;
import java.util.Iterator;
import java.util.concurrent.LinkedBlockingQueue; import android.content.Context;
import android.util.Log; import com.boyaa.push.lib.util.NetworkUtil; /**
*
* @author Administrator
*
*/
public class Client { private final int STATE_OPEN=1;//socket打开
private final int STATE_CLOSE=1<<1;//socket关闭
private final int STATE_CONNECT_START=1<<2;//开始连接server
private final int STATE_CONNECT_SUCCESS=1<<3;//连接成功
private final int STATE_CONNECT_FAILED=1<<4;//连接失败
private final int STATE_CONNECT_WAIT=1<<5;//等待连接 private String IP="192.168.1.100";
private int PORT=60000; private int state=STATE_CONNECT_START; private Socket socket=null;
private OutputStream outStream=null;
private InputStream inStream=null; private Thread conn=null;
private Thread send=null;
private Thread rec=null; private Context context;
private ISocketResponse respListener;
private LinkedBlockingQueue<Packet> requestQueen=new LinkedBlockingQueue<Packet>();
private final Object lock=new Object(); public int send(Packet in)
{
requestQueen.add(in);
synchronized (lock)
{
lock.notifyAll();
}
return in.getId();
} public void cancel(int reqId)
{
Iterator<Packet> mIterator=requestQueen.iterator();
while (mIterator.hasNext())
{
Packet packet=mIterator.next();
if(packet.getId()==reqId)
{
mIterator.remove();
}
}
} public Client(Context context,ISocketResponse respListener)
{
this.context=context;
this.respListener=respListener;
} public boolean isNeedConn()
{
return !((state==STATE_CONNECT_SUCCESS)&&(null!=send&&send.isAlive())&&(null!=rec&&rec.isAlive()));
} public void open()
{
reconn();
} public void open(String host,int port)
{
this.IP=host;
this.PORT=port;
reconn();
} private long lastConnTime=0;
public synchronized void reconn()
{
if(System.currentTimeMillis()-lastConnTime<2000)
{
return;
}
lastConnTime=System.currentTimeMillis(); close();
state=STATE_OPEN;
conn=new Thread(new Conn());
conn.start();
} public synchronized void close()
{
if(state!=STATE_CLOSE)
{
try {
if(null!=socket)
{
socket.close();
}
} catch (Exception e) {
e.printStackTrace();
}finally{
socket=null;
} try {
if(null!=outStream)
{
outStream.close();
}
} catch (Exception e) {
e.printStackTrace();
}finally{
outStream=null;
} try {
if(null!=inStream)
{
inStream.close();
}
} catch (Exception e) {
e.printStackTrace();
}finally{
inStream=null;
} try {
if(null!=conn&&conn.isAlive())
{
conn.interrupt();
}
} catch (Exception e) {
e.printStackTrace();
}finally{
conn=null;
} try {
if(null!=send&&send.isAlive())
{
send.interrupt();
}
} catch (Exception e) {
e.printStackTrace();
}finally{
send=null;
} try {
if(null!=rec&&rec.isAlive())
{
rec.interrupt();
}
} catch (Exception e) {
e.printStackTrace();
}finally{
rec=null;
} state=STATE_CLOSE;
}
requestQueen.clear();
} private class Conn implements Runnable
{
public void run() {
while(state!=STATE_CLOSE)
{
try {
state=STATE_CONNECT_START;
socket=new Socket();
socket.connect(new InetSocketAddress(IP, PORT), 15*1000);
state=STATE_CONNECT_SUCCESS;
} catch (Exception e) {
e.printStackTrace();
state=STATE_CONNECT_FAILED;
} if(state==STATE_CONNECT_SUCCESS)
{
try {
outStream=socket.getOutputStream();
inStream=socket.getInputStream();
} catch (IOException e) {
e.printStackTrace();
} send=new Thread(new Send());
rec=new Thread(new Rec());
send.start();
rec.start();
break;
}
else
{
state=STATE_CONNECT_WAIT;
//如果有网络没有连接上,则定时取连接,没有网络则直接退出
if(NetworkUtil.isNetworkAvailable(context))
{
try {
Thread.sleep(15*1000);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
else
{
break;
}
}
}
}
} private class Send implements Runnable
{
public void run() {
try {
while(state!=STATE_CLOSE&&state==STATE_CONNECT_SUCCESS&&null!=outStream)
{
Packet item;
while(null!=(item=requestQueen.poll()))
{
outStream.write(item.getPacket());
outStream.flush();
item=null;
} synchronized (lock)
{
lock.wait();
}
}
}catch(SocketException e1)
{
e1.printStackTrace();//发送的时候出现异常,说明socket被关闭了(服务器关闭)java.net.SocketException: sendto failed: EPIPE (Broken pipe)
reconn();
}
catch (Exception e) {
e.printStackTrace();
}
}
} private class Rec implements Runnable
{
public void run() { try {
while(state!=STATE_CLOSE&&state==STATE_CONNECT_SUCCESS&&null!=inStream)
{
byte[] bodyBytes=new byte[5];
int offset=0;
int length=5;
int read=0; while((read=inStream.read(bodyBytes, offset, length))>0)
{
if(length-read==0)
{
if(null!=respListener)
{
respListener.onSocketResponse(new String(bodyBytes));
} offset=0;
length=5;
read=0;
continue;
}
offset+=read;
length=5-offset;
} reconn();//走到这一步,说明服务器socket断了
break;
}
}
catch(SocketException e1)
{
e1.printStackTrace();//客户端主动socket.close()会调用这里 java.net.SocketException: Socket closed
}
catch (Exception e2) {
e2.printStackTrace();
} }
}
}

2.使用SocketTool工具进行调试

a.创建Server.点击TCP Server ,点击创建,输入端口号,点击确定(同时要点击启动监听)。

b.在android客户端输入IP和端口,点击打开或者重连,socketTool便可以看见你连上的Client了

c.在客户端输入要发送的文字,点击发送,在socketTool便可以看到你往server里发送的数据了,

在socketTool里输入要往客户端发送的内容,点击发送,便可在手机客户端里看到Server往client发送的数据了

这样就可以Client-Server之间进行数据对发了。

邮箱:zz7zz7zz@163.com

微博:http://weibo.com/u/3209971935

[置顶] android socket 聊天实现与调试的更多相关文章

  1. [置顶] Android开发笔记(成长轨迹)

    分类: 开发学习笔记2013-06-21 09:44 26043人阅读 评论(5) 收藏 Android开发笔记 1.控制台输出:called unimplemented OpenGL ES API ...

  2. [置顶] Android系统移植与调试之------->Amlogic方案编译步骤

    1. 拷贝Amlogic的SourceCode 切换目录到  /home/roco/work/amlogic/SourceCode/mx0831-0525下将mx0831-0525.tgz拷贝到  / ...

  3. [置顶] Android系统移植与调试之------->如何修改Android设备状态条上音量加减键在横竖屏的时候的切换与显示

    这两天由于一个客户的要求,将MID竖屏时候的状态条上的音量键去掉.所以尝试修改了一下,成功了,分享一下经验. 先看一下修改后的效果图,如下所示 . 横屏的时候:有音量加减键 竖屏的时候:音量加减键被去 ...

  4. [置顶] Android系统移植与调试之------->build.prop文件详细赏析

    小知识:什么是build.prop?   /system/build.prop 是一个属性文件,在Android系统中.prop文件很重要,记录了系统的设置和改变,类似於/etc中的文件.这个文件是如 ...

  5. [置顶] Android系统移植与调试之------->如何修改Android设备添加3G上网功能

    1.首先先来看一下修改前后的效果对比图 step1.插上3G设备前 step2.插上3G设备后,获取信号中.... step3.插上3G设备后,获取到信号 step4.使用3G信号浏览网页 2.下面讲 ...

  6. [置顶] Android JNI必须掌握的五点

      1:JNI是什么? Java NativeInterface(JNI)是Java提供的一个很重要的特性.它使得用诸如C/C++等语言编写的代码可以与运行于Java虚拟机(JVM)中的 Java代码 ...

  7. [置顶] Android中使用Movie显示gif动态图

    转载请注明:  http://blog.csdn.net/u012975705/article/details/48717391 在看这篇博文之前对attr自定义属性还是不是很熟的童鞋可以先看看:An ...

  8. Android Socket 聊天室示例

    服务端: package com.test.chatServer; import java.io.IOException; import java.net.ServerSocket; import j ...

  9. [置顶] Android AlarmManager实现不间断轮询服务

    在消息的获取上是选择轮询还是推送得根据实际的业务需要来技术选型,例如对消息实时性比较高的需求,比如微博新通知或新闻等那就最好是用推送了.但如果只是一般的消息检测比如更新检查,可能是半个小时或一个小时一 ...

随机推荐

  1. 批量增加Linux系统账号、重置账号密码、FTP账号批量测试

    批量增加Linux系统账号.重置账号密码是用Linux Shell脚本来做的:批量FTP账号测试是用Python脚本来做的.这些脚本都是读取一个用户名和密码文件,然后基于该用户名密码文件进行自动批量测 ...

  2. python3迭代器和生成器

    1.手动访问迭代器中的元素 #要手动访问迭代器中的元素,可以使用next()函数 In [3]: with open('/etc/passwd') as f: ...: try: ...: while ...

  3. makefile 中 foreach

    四.foreach 函数 foreach函数和别的函数非常的不一样.因为这个函数是用来做循环用的,Makefile中的foreach函数几乎是仿照于Unix标准Shell(/bin/sh)中的for语 ...

  4. 转载 http://blog.csdn.net/dengta_snowwhite/article/details/6418384

    从SDCard保存的txt文件读取中文到android系统中会出现乱码问题,如何解决这个乱码问题,网上有不少解答方法,譬如说利用String temp1 =EncodingUtils.getStrin ...

  5. C#操作Mongo进行数据读写

    C#操作MongoHelp类 using System; using System.Collections.Generic; using System.Linq; using System.Web; ...

  6. PHP实现 APP端微信支付功能

    1.我封装好的一个支付类文件,多余的东西都去除掉了,并且把配置参数放到了这个支付类中,只需要修改Weixinpayandroid方法内的几个参数就可以直接复制使用: class Wxpayandroi ...

  7. react 的JSX语法需要注意哪些点?

    注释方式 ReactDOM.render( <div> {/*JSX 中的注释方式*/} </div>, document.getElementById('root') ) j ...

  8. VirtualBox 安装 Gentoo 小记

    因为需求,尝试了一下在 VirtualBox 安装 Gentoo.虽然多年前就折腾过多次 LFS,但 Gentoo 并没有太多尝试.这次确实也经历了种种波折,到最后总算成功了,大致跨度为3天.本来手上 ...

  9. hdu 1272 判断所给的图是不是生成树 (并查集)

    判断所给的图是不是生成树,如果有环就不是,如果没环但连通分量大于1也不是 find函数 用递归写的话 会无限栈溢出 Orz要加上那一串 手动扩栈 Sample Input6 8 5 3 5 2 6 4 ...

  10. foxmail占cpu 100%解决办法

    Win10,x64 Foxmail 7.2.9.075 解决办法: 1. 删除文件夹 d:\Program Files\Foxmail\Storage\邮箱\Indexes2. 菜单 –>帮助 ...