Socket通讯简单点理解就是通讯双方通过某个端口进行数据的相互传输,与常用的http的请求-响应方式不同,Socket通讯无需客户端向服务器发送请求,然后服务器在响应,直接就是进行数据传输。
一、Socket的类型
Socket有两种类型:
1、基于TCP协议传输数据的streamsocket;
2、基于UDP协议传输数据的datagramsocket。
传输过程如下:
通常我们都使用TCP协议传输
如上图Socket也分为服务器端和客户端,实际上一台机器既可以是服务端也可以是客户端,而两端 之间通过字节流传输数据
二、Socket的具体实现
这里的实现基于TCP协议的方式
1、首先在服务端先创建一个工作线程类来处理数据
public class MessageRunnable implements Runnable{
private Socket socket=null;
public MessageRunnable(Socket socket){
this.socket=socket;
}
@Override
public void run() {
try {
//获取输入输出流
InputStream is=socket.getInputStream();
OutputStream os=socket.getOutputStream();
//把数据写回客户端
// String toClientStr="稍等下..客服忙...";
// os.write(toClientStr.getBytes("utf-8"));
// os.flush();
//停止socket输出(半关闭状态)
// socket.shutdownOutput();
//读取客户端数据
BufferedReader bf=new BufferedReader(new InputStreamReader(is));
String line=null;
String dataFromClient="";
while ((line=bf.readLine())!=null) {
dataFromClient+=line;
}
System.out.println("来自客户端:"+dataFromClient);
socket.shutdownInput();
os.write(dataFromClient.getBytes("utf-8"));
os.flush();
os.close();
is.close();
socket.close();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
主要是获取输入输出流的方法,输入流就是外界接收过来的数据流,输出流就是本地向外界发送的数据流
InputStream is=socket.getInputStream();
OutputStream os=socket.getOutputStream();
2、然后再主线程创建ServerSocket对象
ServerSocket service=new ServerSocket(SOCKET_PORT);
上面方法传递的参数是通讯的端口号
3、通过ServerSocket对象的accept的方法获取来自客户端的socket对象
如果有数据过来就往下执行,否则就处于堵塞状态
while(true){
//监听客户送发过来的信息
Socket socket=service.accept();
new Thread(new MessageRunnable(socket)).start();
}
4、在客户端创建好Socket对象,因为是网络操作所以要授权和在子线程运行,所以这里通过handle的消息机制来更新UI
//构造用于发送socket线程
private class SocketThread extends Thread{
String message;
SocketThread(String messsage){
this.message=messsage;
}
@Override
public void run() {
try {
socket=new Socket();
socket.connect(new InetSocketAddress("192.168.1.100",8888),5000);
//获取输入输出流
InputStream is=socket.getInputStream();
OutputStream os=socket.getOutputStream();
BufferedReader bf=new BufferedReader(new InputStreamReader(is));
os.write(message.getBytes("utf-8"));
os.flush();
String line=null;
String buff="";
while ((line=bf.readLine())!=null){
buff+=line+"\n";
}
//发消息用于展示界面
Message msg=Message.obtain();
msg.what=MESSAGE_FLAG;
Bundle bundle=new Bundle();
bundle.putString("text",buff);
msg.setData(bundle);
handler.sendMessage(msg);
os.close();
is.close();
bf.close();
socket.close();
}catch (SocketTimeoutException e){
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//处理子线程消息
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
if(msg.what==MESSAGE_FLAG){
Bundle bundle=msg.getData();
String message=bundle.getString("text");
tvDisplay.append("Server说:"+message+"\n");
}
super.handleMessage(msg);
}
};
客户端这边通过connect方法连接到服务端的端口实现双方的通讯
三、总结
Socket是对TCP(UDP)协议的应用,主要应用场景是实时通信、游戏之类的要求网络能快速回应而不像http协议那般要发送请求才会获取响应,socket发生的网络连接,端与端之间可以主动推送数据,使数据响应更为及时,当然这样长时间的实时响应是很耗电的,所以一般长时间没有数据传递都会关闭连接。