Socket 有什么用?
- Socket 是进程间通信的一种常用方式
- Windows – Linux – Android 各系统之间高效交互
Socket 代码书写刚开始接触会有点儿难理解,我觉得首先要对Socket有一个全局的认识:
- 通信的关键在于获得一个 socket 对象,获得这个对象就相当于建立了一个长连接,只有某一方主动断开连接,这个长连接才会断开;
- 一个端口可以有多个链接存在,看下图
从上图可以看出,不仅多个客户端可以和服务端的一个端口建立多个连接,并且一个客户端也可以和服务端的一个端口建立多个连接;
所以说 Socket 一个端口可以并行的做不同的事情;
知道了这些之后我们就要开始码代码了,为了便于理解,我将socket 的代码分成了几个模块
服务端:
1、开启监听,等待连接
2、得到 socket 对象,开始交互
3、断开连接
客户端:
1、连接服务端
2、得到 socket 对象,开始交互
3、断开连接
这个过程中我们需要注意的是:
我们先从服务端来看:
1、开启监听,等待连接,得到socket对象
new Thread(new Runnable() {
@Override
public void run() {
if(serverSocket==null){
try {
serverSocket = new ServerSocket(3060);
} catch (IOException e) {
e.printStackTrace();
Log.d(TAG,"fail to new serversocket");
}
}
try {
Log.d(TAG,"作为服务端:我们开始监听!!");
mSocket = serverSocket.accept();// 这是一个阻塞方法
Log.d(TAG,"作为服务端被连接:有设备连接到了我们!!");
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
这段代码注意 serverSocket.accept() 是一段阻塞代码(耗时操作),它的返回值就是我们第二步需要的 socket对象。
将得到的 socket 的对象保存之后,我们就可以继续监听其它的连接了;
2、交互和断开连接
– 获得输入输出流,为交互做准备
private void onConnectSucceed(){
try {
inputStream = mSocket.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
try {
outputStream = mSocket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
//stopListening();
startListeningMessage();
}
– 监听客户端的消息
public void startListeningMessage() {
listenThread = new Thread(new Runnable() {
@Override
public void run() {
inputStreamReader = new InputStreamReader(inputStream);//提高效率,将自己字节流转为字符流
bufferedReader = new BufferedReader(inputStreamReader);//加入缓冲区String temp=null;
String info = "";
String temp = "";
//Log.d(TAG,"服务端检测客户端消息:当前客户端ip为:"+mSocket.getInetAddress().getHostAddress());
try {
while ((temp = bufferedReader.readLine()) != null) {
// 当对方主动断开连接,才会跳出while 循环
info += temp;
Log.d(TAG, "服务端接收到客户端信息:" + info + ",当前客户端ip为:" + mSocket.getInetAddress().getHostAddress());
}
} catch (IOException e) {
e.printStackTrace();
//Log.d(TAG,"服务端监听消息出错:当前客户端ip为:"+mSocket.getInetAddress().getHostAddress());
}
onSocketClosed();//跳出循环,意味着这个socket 连接断开,我们需要将一些不需要的数据释放掉
Log.d(TAG, "服务端监听消息结束!!");
}
});
listenThread.start();
}
– 向客户端发送数据
new Thread(new Runnable() {
@Override
public void run() {
if (outputStream != null) {
try {
writer = new DataOutputStream(outputStream);
writer.writeUTF(msg + " \n"); // 写一个UTF-8的信息
writer.flush();
} catch (IOException e) {
e.printStackTrace();
// 发送消息失败
}
}
}
}).start();
再看一下客户端
客户端与服务端不同的地方只在于,服务端是监听端口,等待客户端来连接
而客户端就是直接连接就可以了
new Thread(new Runnable() {
@Override
public void run() {
try {
sendMegForToast("msg", "作为客户端:我们尝试连接!!");
mSocket = new Socket("192.168.100.153", 3060);// 这也是一个耗时操作
Log.d(TAG, "作为客户端连接成功!");
sendMegForToast("msg", "作为客户端连接成功!");
onConnectSucceed();
} catch (IOException e) {
e.printStackTrace();
Log.d(TAG, "作为客户端尝试连接失败!");
sendMegForToast("msg", "作为客户端尝试连接失败!");
}
}
}).start();
其中
mSocket = new Socket(“192.168.100.153”, 3060);
这段代码也是阻塞的,一段耗时操作,当连接成功之后才会向下执行;
其它部分和服务端完全一致
socket 这个东西,理解基本的用法,明白它的一些关键点,多去把它嵌套到实际的工作任务中,就可以得心应手的使用它了。