先上代码:Tuto: Tuto是一个Socket 客户端 服务端 学习例子
这是一个开源项目,主要用于学习和交流,代码你可以随便抄随便用。
Demo主要实现两个功能:1,客户端和服务端消息的收发 2,客户端和服务端文件的收发
一,客户端和服务端的消息收发
1,程序启动初始化服务端
//MainActivity.java
private void initServer(){
SocketService socketService = new SocketService();
socketService.startService();
}
2,创建线程发送消息
//MainActivity.java
send_msg_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String msg=msg_et.getText().toString();
if(msg!=null&&!msg.equals("")){
mSendMsg.sendMsg(MainActivity.this,msg);
msg_et.setText("");
}
}
});
//SendMsgImpl.java
@Override
public int sendMsg(Context context, String msg) {
ClientThread runnable = new ClientThread();
runnable.setRspListener((IRspListener) context);
byte[] msgBytes = msg.getBytes();
byte[] sendStr = Utils.buildMsg(Utils.int2Bytes_LE(msgBytes.length), msgBytes);
runnable.setmMsg(sendStr);
new Thread(runnable).start();
return 0;
}
//ClientThread.java
@Override
public void run() {
mLock.lock();
try {
Socket socket = null;
try {
socket = new Socket(CommContent.IP,CommContent.PORT);
} catch (IOException e) {
e.printStackTrace();
}
InputStream input = null;
DataOutputStream doutput = null;
OutputStream output = null;
DataInputStream dinput = null;
try {
socket.setSoTimeout(20 * 1000);
output = socket.getOutputStream();
doutput = new DataOutputStream(output);
//向服务端发送数据 REQ
doutput.write(mMsg, 0, mMsg.length);
Log.i(TAG, Thread.currentThread().getName() + " 客户端发送消息:"+ Utils.bytesToHexString(mMsg));
doutput.flush();
input = socket.getInputStream();
dinput = new DataInputStream(input);
byte[] readbuf = new byte[1024];
dinput.read(readbuf);
int dataLen= Utils.bytes2Int_LE(Utils.subByte(readbuf,4,7));
Log.i(TAG,"dataLen:"+dataLen);
String dataStr= Utils.hexBytes2Str(Utils.subByte(readbuf,8,dataLen));
Log.i(TAG, "客户端收到消息:"+dataStr);
mListener.onRspMsg(socket,dataStr);
} catch (SocketTimeoutException e) {
Log.i(TAG, "连接超时");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
input.close();
dinput.close();
output.close();
doutput.close();
Log.i(TAG, "Stream close");
} catch (IOException e) {
e.printStackTrace();
}
}
}finally {
mLock.unlock();
}
}
3,服务端接收到消息后响应消息
//ServiceThread.java
@Override
public void run() {
super.run();
InputStream input = null;//来自客户端的数据
DataInputStream dinput = null;
OutputStream output = null;//发送给客户端的数据
DataOutputStream doutput = null;
try {
input = socket.getInputStream();
if(SocketService.mType==1){
dinput = new DataInputStream(input);
byte[] readbuf=new byte[1024];
dinput.read(readbuf);
int dataLen= Utils.bytes2Int_LE(Utils.subByte(readbuf,4,7));
Log.i(TAG,"dataLen:"+dataLen);
String dataStr= Utils.hexBytes2Str(Utils.subByte(readbuf,8,dataLen));
Log.i(TAG, "服务端收到消息:"+dataStr);
if(dataStr.equals(CommContent.SEND_FILE)){
//客户端发起传输文件流程
SocketService.mType=2;
//服务端响应客户端请求
output = socket.getOutputStream();
doutput = new DataOutputStream(output);
byte[] rep=CommContent.SEND_FILE.getBytes();
byte[] repStr= Utils.buildMsg(Utils.int2Bytes_LE(rep.length),rep);
doutput.write(repStr,0,repStr.length);
Log.i(TAG, "服务端响应消息:"+ Utils.bytesToHexString(repStr));
doutput.flush();
}else if(dataStr.equals(CommContent.DOWLOAD_FILE)){
//客户端发起传输文件流程
SocketService.mType=3;
//服务端响应客户端请求
output = socket.getOutputStream();
doutput = new DataOutputStream(output);
byte[] rep=CommContent.DOWLOAD_FILE.getBytes();
byte[] repStr= Utils.buildMsg(Utils.int2Bytes_LE(rep.length),rep);
doutput.write(repStr,0,repStr.length);
Log.i(TAG, "服务端响应消息:"+ Utils.bytesToHexString(repStr));
doutput.flush();
//服务端向客户端传输文件
output = socket.getOutputStream();
doutput = new DataOutputStream(output);
File file = new File(MainActivity.path+"serviceFile.txt");
DataInputStream fileInputStream = new DataInputStream(new FileInputStream(file));
byte[] buf = new byte[1024];
int len = 0;
Log.i(TAG, Thread.currentThread().getName() + " 向客户端发送文件");
while ((len = fileInputStream.read(buf)) != -1) {
doutput.write(buf, 0, len);
}
Log.i(TAG, "文件传输完成!!");
doutput.flush();
fileInputStream.close();
SocketService.mType=1;
}else {
SocketService.mType=1;
output = socket.getOutputStream();
doutput = new DataOutputStream(output);
byte[] rep="server response".getBytes();
byte[] repStr= Utils.buildMsg(Utils.int2Bytes_LE(rep.length),rep);
doutput.write(repStr,0,repStr.length);
Log.i(TAG, "服务端响应消息:"+ Utils.bytesToHexString(repStr));
doutput.flush();
}
}else if(SocketService.mType==2){
//处理文件接收任务
Log.i(TAG, "接收客户端的文件");
dinput=new DataInputStream(input);
Date date=new Date();
DataOutputStream fileDataOutputStream=new DataOutputStream(new FileOutputStream(MainActivity.path+"serviceFile"+date.getTime()+".txt"));
byte[] buf=new byte[1024];
int len=0;
while ((len=dinput.read(buf))!=-1){
fileDataOutputStream.write(buf,0,len);
Log.i(TAG, "写入文件... "+len);
}
Log.i(TAG, "文件下载完成!!");
fileDataOutputStream.flush();
fileDataOutputStream.close();
SocketService.mType=1;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(input!=null){
input.close();
}
if(dinput!=null){
dinput.close();
}
if(output!=null){
output.close();
}
if(doutput!=null){
doutput.close();
}
Log.i(TAG, "Stream close");
} catch (IOException e) {
e.printStackTrace();
}
}
}
二,客户端和服务端的文件收发
1,客户端先向服务发送消息请求传输文件,并注册消息监听,服务端响应后启动文件传输流程
//SendMsgImpl.java
@Override
public int sendFile(Context context, String filePath) {
ClientThread runnable = new ClientThread();
runnable.setRspListener(new IRspListener() {
private ReentrantLock mLock = new ReentrantLock(true);
@Override
public void onTimeOut() {
}
@Override
public void onRspMsg(Socket sockets, String msg) {
if (msg.equals(CommContent.SEND_FILE)) {
mLock.lock();
try {
Socket socket = null;
try {
socket = new Socket(CommContent.IP, CommContent.PORT);
} catch (IOException e) {
e.printStackTrace();
}
InputStream input = null;
DataOutputStream doutput = null;
OutputStream output = null;
DataInputStream dinput = null;
try {
socket.setSoTimeout(5 * 60 * 1000);
output = socket.getOutputStream();
doutput = new DataOutputStream(output);
File file = new File(filePath);
DataInputStream fileInputStream = new DataInputStream(new FileInputStream(file));
byte[] buf = new byte[1024];
int len = 0;
Log.i(TAG, Thread.currentThread().getName() + " 向服务端发送文件");
while ((len = fileInputStream.read(buf)) != -1) {
doutput.write(buf, 0, len);
}
Log.i(TAG, "文件传输完成!!");
doutput.flush();
fileInputStream.close();
} catch (SocketTimeoutException e) {
Log.i(TAG, "连接超时");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (input != null) {
input.close();
}
if (dinput != null) {
dinput.close();
}
if (output != null) {
output.close();
}
if (doutput != null) {
doutput.close();
}
Log.i(TAG, "Stream close");
} catch (IOException e) {
e.printStackTrace();
}
}
} finally {
mLock.unlock();
}
}
}
});
byte[] msgBytes = CommContent.SEND_FILE.getBytes();
byte[] sendStr = Utils.buildMsg(Utils.int2Bytes_LE(msgBytes.length), msgBytes);
runnable.setmMsg(sendStr);
new Thread(runnable).start();
return 0;
}
2,服务端收到客户端的文件传输请求,切换成文件接收模式,并接收客户端传输的文件
//ServiceThread.java
if(dataStr.equals(CommContent.SEND_FILE)){
//客户端发起传输文件流程
SocketService.mType=2;
//服务端响应客户端请求
output = socket.getOutputStream();
doutput = new DataOutputStream(output);
byte[] rep=CommContent.SEND_FILE.getBytes();
byte[] repStr= Utils.buildMsg(Utils.int2Bytes_LE(rep.length),rep);
doutput.write(repStr,0,repStr.length);
Log.i(TAG, "服务端响应消息:"+ Utils.bytesToHexString(repStr));
doutput.flush();
}else if(SocketService.mType==2){
//处理文件接收任务
Log.i(TAG, "接收客户端的文件");
dinput=new DataInputStream(input);
Date date=new Date();
DataOutputStream fileDataOutputStream=new DataOutputStream(new FileOutputStream(MainActivity.path+"serviceFile"+date.getTime()+".txt"));
byte[] buf=new byte[1024];
int len=0;
while ((len=dinput.read(buf))!=-1){
fileDataOutputStream.write(buf,0,len);
Log.i(TAG, "写入文件... "+len);
}
Log.i(TAG, "文件下载完成!!");
fileDataOutputStream.flush();
fileDataOutputStream.close();
SocketService.mType=1;
}