您的位置:首页 > 移动开发 > Android开发

[置顶] android socket 聊天实现与调试

2013-07-22 19:21 447 查看
网上很多基于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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: