实现流程:
服务端
package com.jzj.socket;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
/**
* Socket收发器 通过Socket发送数据,并使用新线程监听Socket接收到的数据
*
* @author jzj1993
* @since 2015-2-22
*/
public abstract class SocketTransceiver implements Runnable {
protected Socket socket;
protected InetAddress addr;
protected DataInputStream in;
protected DataOutputStream out;
private boolean runFlag;
/**
* 实例化
*
* @param socket
* 已经建立连接的socket
*/
public SocketTransceiver(Socket socket) {
this.socket = socket;
this.addr = socket.getInetAddress();
}
/**
* 获取连接到的Socket地址
*
* @return InetAddress对象
*/
public InetAddress getInetAddress() {
return addr;
}
/**
* 开启Socket收发
* <p>
* 如果开启失败,会断开连接并回调{@code onDisconnect()}
*/
public void start() {
runFlag = true;
new Thread(this).start();
}
/**
* 断开连接(主动)
* <p>
* 连接断开后,会回调{@code onDisconnect()}
*/
public void stop() {
runFlag = false;
try {
socket.shutdownInput();
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 发送字符串
*
* @param s
* 字符串
* @return 发送成功返回true
*/
public boolean send(String s) {
if (out != null) {
try {
out.writeUTF(s);
out.flush();
return true;
} catch (Exception e) {
e.printStackTrace();
}
}
return false;
}
/**
* 监听Socket接收的数据(新线程中运行)
*/
@Override
public void run() {
try {
in = new DataInputStream(this.socket.getInputStream());
out = new DataOutputStream(this.socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
runFlag = false;
}
while (runFlag) {
try {
final String s = in.readUTF();
this.onReceive(addr, s);
} catch (IOException e) {
// 连接被断开(被动)
runFlag = false;
}
}
// 断开连接
try {
in.close();
out.close();
socket.close();
in = null;
out = null;
socket = null;
} catch (IOException e) {
e.printStackTrace();
}
this.onDisconnect(addr);
}
/**
* 接收到数据
* <p>
* 注意:此回调是在新线程中执行的
*
* @param addr
* 连接到的Socket地址
* @param s
* 收到的字符串
*/
public abstract void onReceive(InetAddress addr, String s);
/**
* 连接断开
* <p>
* 注意:此回调是在新线程中执行的
*
* @param addr
* 连接到的Socket地址
*/
public abstract void onDisconnect(InetAddress addr);
}
TCP连接工具类
package com.jzj.socket;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
/**
* TCP Socket服务器端
*
* @author jzj1993
* @since 2015-2-22
*/
public abstract class TcpServer implements Runnable {
private int port;
private boolean runFlag;
private List<SocketTransceiver> clients = new ArrayList<SocketTransceiver>();
/**
* 实例化
*
* @param port
* 监听的端口
*/
public TcpServer(int port) {
this.port = port;
}
/**
* 启动服务器
* <p>
* 如果启动失败,会回调{@code onServerStop()}
*/
public void start() {
runFlag = true;
new Thread(this).start();
}
/**
* 停止服务器
* <p>
* 服务器停止后,会回调{@code onServerStop()}
*/
public void stop() {
runFlag = false;
}
/**
* 监听端口,接受客户端连接(新线程中运行)
*/
@Override
public void run() {
try {
final ServerSocket server = new ServerSocket(port);
while (runFlag) {
try {
final Socket socket = server.accept();
startClient(socket);
} catch (IOException e) {
// 接受客户端连接出错
e.printStackTrace();
this.onConnectFailed();
}
}
// 停止服务器,断开与每个客户端的连接
try {
for (SocketTransceiver client : clients) {
client.stop();
}
clients.clear();
server.close();
} catch (Exception e) {
e.printStackTrace();
}
} catch (IOException e) {
// ServerSocket对象创建出错,服务器启动失败
e.printStackTrace();
}
this.onServerStop();
}
/**
* 启动客户端收发
*
* @param socket
*/
private void startClient(final Socket socket) {
SocketTransceiver client = new SocketTransceiver(socket) {
@Override
public void onReceive(InetAddress addr, String s) {
TcpServer.this.onReceive(this, s);
}
@Override
public void onDisconnect(InetAddress addr) {
clients.remove(this);
TcpServer.this.onDisconnect(this);
}
};
client.start();
clients.add(client);
this.onConnect(client);
}
/**
* 客户端:连接建立
* <p>
* 注意:此回调是在新线程中执行的
*
* @param client
* SocketTransceiver对象
*/
public abstract void onConnect(SocketTransceiver client);
/**
* 客户端:连接建立失败
* <p>
* 注意:此回调是在新线程中执行的
*/
public abstract void onConnectFailed();
/**
* 客户端:收到字符串
* <p>
* 注意:此回调是在新线程中执行的
*
* @param client
* SocketTransceiver对象
* @param s
* 字符串
*/
public abstract void onReceive(SocketTransceiver client, String s);
/**
* 客户端:连接断开
* <p>
* 注意:此回调是在新线程中执行的
*
* @param client
* SocketTransceiver对象
*/
public abstract void onDisconnect(SocketTransceiver client);
/**
* 服务器停止
* <p>
* 注意:此回调是在新线程中执行的
*/
public abstract void onServerStop();
}
测试类:
package com.jzj.socket;
public class ClsMainServer {
public static void main(String[] args) {
int port = 1234;
TcpServer server = new TcpServer(port) {
@Override
public void onConnect(SocketTransceiver client) {
printInfo(client, "Connect");
}
@Override
public void onConnectFailed() {
System.out.println("Client Connect Failed");
}
@Override
public void onReceive(SocketTransceiver client, String s) {
printInfo(client, "Send Data: " + s);
if(s.equals("天王盖地虎")){
client.send("小鸡炖蘑菇"+"\n");
}else if(s.equals("有朋自远方来")){
client.send("必诛之"+"\n");
}else if(s.equals("芝麻开门")){
client.send("不开就不开"+"\n");
}else {
s = s.replace("吗","");
s = s.replace("?","!");
s = s.replace("?","!");
client.send(s+"\n");
}
}
@Override
public void onDisconnect(SocketTransceiver client) {
printInfo(client, "Disconnect");
}
@Override
public void onServerStop() {
System.out.println("--------Server Stopped--------");
}
};
System.out.println("--------Server Started--------");
server.start();
}
static void printInfo(SocketTransceiver st, String msg) {
System.out.println("Client " + st.getInetAddress().getHostAddress());
System.out.println(" " + msg);
}
}
安卓端;
package com.jzj.socket;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
/**
* Socket收发器 通过Socket发送数据,并使用新线程监听Socket接收到的数据
*
* @author jzj1993
* @since 2015-2-22
*/
public abstract class SocketTransceiver implements Runnable {
protected Socket socket;
protected InetAddress addr;
protected DataInputStream in;
protected DataOutputStream out;
private boolean runFlag;
/**
* 实例化
*
* @param socket
* 已经建立连接的socket
*/
public SocketTransceiver(Socket socket) {
this.socket = socket;
this.addr = socket.getInetAddress();
}
/**
* 获取连接到的Socket地址
*
* @return InetAddress对象
*/
public InetAddress getInetAddress() {
return addr;
}
/**
* 开启Socket收发
* <p>
* 如果开启失败,会断开连接并回调{@code onDisconnect()}
*/
public void start() {
runFlag = true;
new Thread(this).start();
}
/**
* 断开连接(主动)
* <p>
* 连接断开后,会回调{@code onDisconnect()}
*/
public void stop() {
runFlag = false;
try {
socket.shutdownInput();
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 发送字符串
*
* @param s
* 字符串
* @return 发送成功返回true
*/
public boolean send(String s) {
if (out != null) {
try {
out.writeUTF(s);
out.flush();
return true;
} catch (Exception e) {
e.printStackTrace();
}
}
return false;
}
/**
* 监听Socket接收的数据(新线程中运行)
*/
@Override
public void run() {
try {
in = new DataInputStream(this.socket.getInputStream());
out = new DataOutputStream(this.socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
runFlag = false;
}
while (runFlag) {
try {
final String s = in.readUTF();
this.onReceive(addr, s);
} catch (IOException e) {
// 连接被断开(被动)
runFlag = false;
}
}
// 断开连接
try {
in.close();
out.close();
socket.close();
in = null;
out = null;
socket = null;
} catch (IOException e) {
e.printStackTrace();
}
this.onDisconnect(addr);
}
/**
* 接收到数据
* <p>
* 注意:此回调是在新线程中执行的
*
* @param addr
* 连接到的Socket地址
* @param s
* 收到的字符串
*/
public abstract void onReceive(InetAddress addr, String s);
/**
* 连接断开
* <p>
* 注意:此回调是在新线程中执行的
*
* @param addr
* 连接到的Socket地址
*/
public abstract void onDisconnect(InetAddress addr);
}
package com.jzj.socket;
import java.net.InetAddress;
import java.net.Socket;
/**
* TCP Socket客户端
*
* @author jzj1993
* @since 2015-2-22
*/
public abstract class TcpClient implements Runnable {
private int port;
private String hostIP;
private boolean connect = false;
private SocketTransceiver transceiver;
/**
* 建立连接
* <p>
* 连接的建立将在新线程中进行
* <p>
* 连接建立成功,回调{@code onConnect()}
* <p>
* 连接建立失败,回调{@code onConnectFailed()}
*
* @param hostIP
* 服务器主机IP
* @param port
* 端口
*/
public void connect(String hostIP, int port) {
this.hostIP = hostIP;
this.port = port;
new Thread(this).start();
}
@Override
public void run() {
try {
Socket socket = new Socket(hostIP, port);
transceiver = new SocketTransceiver(socket) {
@Override
public void onReceive(InetAddress addr, String s) {
TcpClient.this.onReceive(this, s);
}
@Override
public void onDisconnect(InetAddress addr) {
connect = false;
TcpClient.this.onDisconnect(this);
}
};
transceiver.start();
connect = true;
this.onConnect(transceiver);
} catch (Exception e) {
e.printStackTrace();
this.onConnectFailed();
}
}
/**
* 断开连接
* <p>
* 连接断开,回调{@code onDisconnect()}
*/
public void disconnect() {
if (transceiver != null) {
transceiver.stop();
transceiver = null;
}
}
/**
* 判断是否连接
*
* @return 当前处于连接状态,则返回true
*/
public boolean isConnected() {
return connect;
}
/**
* 获取Socket收发器
*
* @return 未连接则返回null
*/
public SocketTransceiver getTransceiver() {
return isConnected() ? transceiver : null;
}
/**
* 连接建立
*
* @param transceiver
* SocketTransceiver对象
*/
public abstract void onConnect(SocketTransceiver transceiver);
/**
* 连接建立失败
*/
public abstract void onConnectFailed();
/**
* 接收到数据
* <p>
* 注意:此回调是在新线程中执行的
*
* @param transceiver
* SocketTransceiver对象
* @param s
* 字符串
*/
public abstract void onReceive(SocketTransceiver transceiver, String s);
/**
* 连接断开
* <p>
* 注意:此回调是在新线程中执行的
*
* @param transceiver
* SocketTransceiver对象
*/
public abstract void onDisconnect(SocketTransceiver transceiver);
}
package com.demo.main;
import com.jzj.socket.SocketTransceiver;
import com.jzj.socket.TcpClient;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity implements OnClickListener {
private Button bnConnect;
private TextView txReceive;
private EditText edIP, edPort, edData;
private Handler handler = new Handler(Looper.getMainLooper());
private TcpClient client = new TcpClient() {
@Override
public void onConnect(SocketTransceiver transceiver) {
refreshUI(true);
}
@Override
public void onDisconnect(SocketTransceiver transceiver) {
refreshUI(false);
}
@Override
public void onConnectFailed() {
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "连接失败",
Toast.LENGTH_SHORT).show();
}
});
}
@Override
public void onReceive(SocketTransceiver transceiver, final String s) {
handler.post(new Runnable() {
@Override
public void run() {
txReceive.append(s);
}
});
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.findViewById(R.id.bn_send).setOnClickListener(this);
bnConnect = (Button) this.findViewById(R.id.bn_connect);
bnConnect.setOnClickListener(this);
edIP = (EditText) this.findViewById(R.id.ed_ip);
edPort = (EditText) this.findViewById(R.id.ed_port);
edData = (EditText) this.findViewById(R.id.ed_dat);
txReceive = (TextView) this.findViewById(R.id.tx_receive);
txReceive.setOnClickListener(this);
refreshUI(false);
}
@Override
public void onStop() {
client.disconnect();
super.onStop();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bn_connect:
connect();
break;
case R.id.bn_send:
sendStr();
break;
case R.id.tx_receive:
clear();
break;
}
}
/**
* 刷新界面显示
*
* @param isConnected
*/
private void refreshUI(final boolean isConnected) {
handler.post(new Runnable() {
@Override
public void run() {
edPort.setEnabled(!isConnected);
edIP.setEnabled(!isConnected);
bnConnect.setText(isConnected ? "断开" : "连接");
}
});
}
/**
* 设置IP和端口地址,连接或断开
*/
private void connect() {
if (client.isConnected()) {
// 断开连接
client.disconnect();
} else {
try {
String hostIP = edIP.getText().toString();
int port = Integer.parseInt(edPort.getText().toString());
client.connect(hostIP, port);
} catch (NumberFormatException e) {
Toast.makeText(this, "端口错误", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
}
/**
* 发送数据
*/
private void sendStr() {
try {
String data = edData.getText().toString();
client.getTransceiver().send(data);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 清空接收框
*/
private void clear() {
new AlertDialog.Builder(this).setTitle("确认清除?")
.setNegativeButton("取消", null)
.setPositiveButton("确认", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
txReceive.setText("");
}
}).show();
}
}