应用场景:

两台android机器:一台自建wifi热点,另一台搜索到,连接该wifi热点。之后再通过socket传递消息,文件等,当服务器端接收到消息之后会返回对应的应答消息;

注意点:接收到消息之后不能直接拔dos关闭了,这样会造成socket关闭;

socket关闭只需要一端关闭即可;

这里发送没有使用缓存发送,每一次writeInt的时候度会直接发送出去,,因此可以不需要flush();

每一次的发送端的 write 和 接收端的read  必须对应,否则异常出错!

服务器端socket代码:

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import com.carspeak.client.entity.NetTransEntity;
import com.carspeak.terminal.utils.AppUtils;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Log; /**
* 服务器端完整socket接收代码(接收客户端的图片)
* @author huqiang
*
*/
public class SocketService implements Runnable{
private static final String TAG = "SocketService"; private ServerSocket serviceSocket;
private boolean SCAN_FLAG = false; // 接收扫描标识
private boolean REV_FLAG = false; // 接收标识 private static String mfilePath = null; // 存放接收文件的路径 private static Context mContext;
private static SocketService instance; // 唯一实例
private Thread mThread;
private boolean IS_THREAD_STOP = false; // 是否线程开始标志 private static Handler mHandler;
public SocketService()
{
try
{
serviceSocket = new ServerSocket(4700);
Log.d(TAG, "建立监听服务器ServerSocket成功");
} catch (IOException e)
{
Log.d(TAG, "建立监听服务器ServerSocket失败");
e.printStackTrace();
}
mThread = new Thread(this);
} /**
* <p>
* 获取TcpService实例
* <p>
* 单例模式,返回唯一实例
*/
public static SocketService getInstance(Context context,Handler handler,String filepath)
{
mContext = context;
mHandler = handler;
mfilePath = filepath;
if (instance == null)
{
instance = new SocketService();
}
return instance;
} public void setSavePath(String fileSavePath)
{
Log.d(TAG, "设置存储路径成功,路径为" + fileSavePath);
this.mfilePath = fileSavePath;
// REV_FLAG=true;
} public SocketService(Context context)
{
this();
mContext = context;
} private void scan_recv()
{
try
{
Socket socket = serviceSocket.accept(); // 接收UDP数据报
// socket.setSoTimeout(10*1000); // 设置掉线时间
Log.d(TAG, "客户端连接成功");
//通过子线程来循环读取socket的消息
ListenClientSocket ls = new ListenClientSocket(socket);
ls.start(); } catch (IOException e)
{
e.printStackTrace();
Log.d(TAG, "客户端连接失败");
SCAN_FLAG = false;
}
} @Override
public void run()
{
Log.d(TAG, "TCP_Service线程开启");
while (!IS_THREAD_STOP)
{
if (SCAN_FLAG)
{
scan_recv();
}
}
} public void release()
{
if (null != serviceSocket && !serviceSocket.isClosed())
try
{
serviceSocket.close();
serviceSocket = null;
Log.d(TAG, "关闭socket成功");
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
while (SCAN_FLAG == true)
;// 直到SCAN_FLAG为false的时候退出循环
SCAN_FLAG = false;
IS_THREAD_STOP = true;
} public void startReceive()
{
SCAN_FLAG = true; // 使能扫描接收标识
if (!mThread.isAlive())
mThread.start(); // 开启线程
} public void stopReceive()
{
while (SCAN_FLAG == true)
;
SCAN_FLAG = false; // 失能扫描接收标识
} /**
* 监听客户端发送的消息
* @author huqiang
*
*/
class ListenClientSocket implements Runnable
{
private boolean IsListening = false;
private Socket clientSocket;
private Thread thread;
public ListenClientSocket(Socket s)
{
this.clientSocket = s;
this.thread = new Thread(this);
}
@Override
public void run() {
while(clientSocket!=null&&!clientSocket.isClosed()&&IsListening)
{
readMessage(this.clientSocket);
}
}
public void start()
{
IsListening = true;
thread.start();
}
public void release()
{
IsListening = false;
if(!clientSocket.isClosed())
{
try {
clientSocket.close();
clientSocket = null;
} catch (IOException e) {
e.printStackTrace();
} }
}
public void readMessage(Socket socket)
{
NetTransEntity entity = new NetTransEntity();
try
{
//分批次接收socket
InputStream in = socket.getInputStream();
DataInputStream dis = new DataInputStream(in);
entity.RequestCode = dis.readInt();
entity.params = dis.readUTF();
switch(entity.RequestCode)
{
case 100://
case 500://请求升级
Log.v(TAG, "请求图片");
entity.fileLength = dis.readLong();
Log.v(TAG, "接收到文件长度:"+entity.fileLength);
if(entity.RequestCode==100)
{
entity.params = "screen.png";
}
FileOutputStream fos =new FileOutputStream(new File(mfilePath,entity.params)); byte[] sendBytes =new byte[1024];
int transLen =0;
Log.v(TAG, "----开始接收文件<" + entity.params +">,文件大小为<" + entity.fileLength +">----");
while(true){
int read =0;
read = dis.read(sendBytes);
Log.v(TAG, "read="+read);
if(read == -1)
break;
transLen += read;
Log.v(TAG, "接收文件进度" +100 * transLen/entity.fileLength +"%...");
fos.write(sendBytes,0, read);
fos.flush();
}
Log.v(TAG, "----接收文件<" + entity.params +">成功-------1");
entity.filePath = mfilePath + entity.params; //将下载下来的文件名字赋值给entity.filePath
Log.v(TAG, "----接收文件<" + entity.params +">成功-------2");
break;
case 101://请求终止投影
case 102://请求待机(超时自动待机)
case 103://请求高速自动待机
break;
case 501://请求固件版本信息
break;
default://其他请求
break;
}
// dis.close();//会造成关闭socket
// socket.shutdownInput();
//发送返回消息
Log.v(TAG, "----开始发送返回消息-------");
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
Log.v(TAG, "发送返回消息 1");
dos.writeInt(200);
dos.flush();
Log.v(TAG, "发送返回消息 2");
switch(entity.RequestCode)
{
case 501: //请求固件版本信息
//返回版本号
Log.v(TAG, "发送返回消息-返回版本号");
String versionCode = AppUtils.getVersionCode(mContext)+"";
dos.writeUTF(versionCode);
dos.flush();
break;
case 100:
case 101:
case 102:
case 103:
default:
dos.writeUTF("success");
dos.flush();
break;
}
// dos.close();
// socket.close();
}
catch(Exception ex)
{
Log.e(TAG, "Exception:"+ex.getMessage()); }
finally
{
Message msg = new Message();
msg.what = 1; //说明有socket消息
msg.obj = entity;
mHandler.sendMessage(msg);
release();
}
} }
}

对应的客户端socket代码:

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket; import com.carspeak.client.config.SPConfig;
import com.carspeak.client.entity.CusMessage;
import com.carspeak.client.entity.NetTransEntity;
import com.carspeak.client.util.SPUtils;
import com.carspeak.client.util.WifiUtils; import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Log; /**
* 连接到终端设备
*
* @author huqiang
*
*/
public class ClientService implements Runnable{ // AppConfig app;
// String filePath;
NetTransEntity mEntity;
String ServerIP;
WifiUtils mWifiUtils;
private final int SERVER_PORT = 4700; //服务器端口
private final int TIME_OUT = 6*1000; //SOCKET超时时间
private Context mContext;
private Handler mHandler;
public ClientService(Context context,Handler handler,NetTransEntity entity) {
// app = (AppConfig) context.getApplicationContext();
// this.filePath = filePath;
this.mEntity = entity;
mContext = context;
this.mHandler = handler;
mWifiUtils = WifiUtils.getInstance(context);
ServerIP = (mWifiUtils.getServerIPAddress()==null)?"192.168.43.1":mWifiUtils.getServerIPAddress();
} /**
* 向终端发送数据
* @param path
* @throws IOException
* @throws Exception
*/
private void sendMessage(NetTransEntity entity) throws IOException, Exception {
// 1.连接服务器
Socket socket = new Socket();
Log.v("ConnectTerminalServer", "开始准备socket连接,ServerIP=" + ServerIP+ ";SERVER_PORT=" + SERVER_PORT + ";TIME_OUT=" + TIME_OUT+";当前连接状态:getSSID"+mWifiUtils.getSSID());
socket.connect(new InetSocketAddress(ServerIP, SERVER_PORT), TIME_OUT); DataOutputStream dos = new DataOutputStream(socket.getOutputStream()); Log.v("ClientService", "开始写入请求码:"+entity.RequestCode);
dos.writeInt(entity.RequestCode); //写入请求码
// dos.flush();
switch(entity.RequestCode)
{
case 100://请求图片
case 500://请求固件升级,发送apk文件
File file = new File(entity.filePath);
Log.v("ClientService", "开始写入文件名 file.getName()="+file.getName());
dos.writeUTF(file.getName()); //第二次写入参数信息
dos.flush();
Log.v("ClientService", "开始写入文件长度 file.length()="+file.length());
dos.writeLong(file.length()); //第三次写入文件的长度
dos.flush();
//第四次写入文件
//传输文件
FileInputStream fis =new FileInputStream(file);
byte[] sendBytes =new byte[1024];
int length =0;
while((length = fis.read(sendBytes,0, sendBytes.length)) >0){
dos.write(sendBytes,0, length);
dos.flush();
}
fis.close();
break;
case 101://请求终止
case 102://请求待机(超时自动待机)
case 103://请求高速自动待机
Log.v("ClientService", "开始写入参数="+(entity.params==null?"params is null":entity.params));
dos.writeUTF(entity.params==null?" ":entity.params);
dos.flush();
break;
case 501://请求固件版本信息
dos.writeUTF(" ");
dos.flush();
break;
default://其他请求
break;
} Log.v("ClientService", "即将关闭dos");
// dos.close(); //注意这里dos关闭会造成socket关闭,应该使用shutdownOutput
socket.shutdownOutput();
Log.v("ClientService", "shutdownOutput");
/****************接收返回参数******************/
DataInputStream dis = new DataInputStream(socket.getInputStream());
CusMessage cms = new CusMessage();
Log.v("ClientService", "接收消息 1 dis="+dis);
cms.code = dis.readInt();
Log.v("ClientService", "接收消息 2");
cms.message = dis.readUTF();
Log.v("ClientService", "接收到终端返回消息,code="+cms.code + ";message="+cms.message);
switch(entity.RequestCode)
{
case 501: //请求固件版本信息
if(cms.code==200)
{
int terminalVersionCode = Integer.parseInt(cms.message);
SPUtils.put(mContext, SPConfig.TerminalVersionCode, -1);
Message msg = new Message();
msg.what = 501;
msg.obj = terminalVersionCode;
mHandler.sendMessage(msg);
Log.v("ClientService", "接收到终端的消息返回,版本号:"+terminalVersionCode);
}
break;
case 100:
case 101:
case 102:
case 103:
default:
break;
}
dos.close();
dis.close();
socket.close();
} @Override
public void run() {
try
{
sendMessage(this.mEntity);
}
catch(IOException ex){
Log.v("ConnectTerminalServer", ex.getMessage());
}
catch (Exception ex) {
Log.v("ConnectTerminalServer", ex.getMessage());
}
} }

android开发之socket快传文件以及消息返回的更多相关文章

  1. Android开发之SD卡上文件操作

    1. 得到存储设备的目录:/SDCARD(一般情况下) SDPATH=Environment.getExternalStorageDirectory()+"/"; 2. 判断SD卡 ...

  2. android开发之路10(文件的读写)

    1.安卓中文件的数据存储实例(将文件保存到手机自带存储空间中): ①MainActivity.java public class MainActivity extends Activity imple ...

  3. Android 开发之旅:深入分析布局文件&又是“Hello World!”

    http://www.cnblogs.com/skynet/archive/2010/05/20/1740277.html 引言 上篇可以说是一个分水岭,它标志着我们从Android应用程序理论进入实 ...

  4. Android开发之InstanceState详解

    Android开发之InstanceState详解   本文介绍Android中关于Activity的两个神秘方法:onSaveInstanceState() 和 onRestoreInstanceS ...

  5. Android开发之InstanceState详解(转)---利用其保存Activity状态

    Android开发之InstanceState详解   本文介绍Android中关于Activity的两个神秘方法:onSaveInstanceState() 和 onRestoreInstanceS ...

  6. 【Android UI】Android开发之View的几种布局方式及实践

    引言 通过前面两篇: Android 开发之旅:又见Hello World! Android 开发之旅:深入分析布局文件&又是“Hello World!” 我们对Android应用程序运行原理 ...

  7. Android开发之旅: Intents和Intent Filters(理论部分)

    引言 大部分移动设备平台上的应用程序都运行在他们自己的沙盒中.他们彼此之间互相隔离,并且严格限制应用程序与硬件和原始组件之间的交互. 我们知道交流是多么的重要,作为一个孤岛没有交流的东西,一定毫无意义 ...

  8. Android开发之Java必备基础

    Android开发之Java必备基础 Java类型系统 Java语言基础数据类型有两种:对象和基本类型(Primitives).Java通过强制使用静态类型来确保类型安全,要求每个变量在使用之前必须先 ...

  9. Android如何实现茄子快传

    Android如何实现茄子快传茄子快传是一款文件传输应用,相信大家都很熟悉这款应用,应该很多人用过用来文件的传输.它有两个核心的功能: 端到端的文件传输Web端的文件传输这两个核心的功能我们具体来分析 ...

随机推荐

  1. JsonHelper类(序列化和反序列化辅助类)

       1: using System; 2: using System.Collections.Generic; 3: using System.Linq; 4: using System.Web; ...

  2. 各个手机APP客户端内置浏览器useragent

    手机QQ Mozilla/5.0 (Linux; Android 4.4.2; GT-I9500 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko ...

  3. 64位系统下注册32位dll文件

    64位系统下注册32位dll文件 在64位系统里注册32位软件所需的一些dll会提示不兼容,大概因为32 位进程不能加载64位Dll,64位进程也不可以加载32的导致. 若要支持的32 位和64 位C ...

  4. Ubuntu中设置永久的DNS

    通过修改: sudo vi /etc/resolvconf/resolv.conf.d/base(这个文件默认是空的) 在里面插入:nameserver 8.8.8.8nameserver 8.8.4 ...

  5. 20141128--JavaScript HTML DOM

    通过 HTML DOM,可访问 JavaScript HTML 文档的所有元素. HTML DOM 当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model). 每个 ...

  6. HTML5-draggable(拖放)

                                                   <!DOCTYPE html> <html class="no-js" ...

  7. nginx配置:支持phpfastcgi,nginx和php-cgi通信,部分nginx常量解释

    支持phpfastcgi的配置如下: server { listen       8000; server_name  localhost; root F:/home/projects/test; i ...

  8. mysql手工注入

    以下是mynona本人原创的,奉献给大家,不要小看数据库注入 参考: http://www.daydaydata.com/help/sql/advance/limit.html http://www. ...

  9. js读取json数据(php传值给js)

    <?php $array =array('fds','fdsa','fdsafasd');  // json_encode($array); ?> <html> <hea ...

  10. 【转】Linux Framebuffer

    全面的framebuffer详解 一.FrameBuffer的原理 FrameBuffer 是出现在 2.2.xx 内核当中的一种驱动程序接口. Linux是工作在保护模式下,所以用户态进程是无法象D ...