相关
Android—网络编程之Http协议
Android—网络编程之OkHttp3整体结构了解以及使用
Android—网络编程之Okhttp3源码解析
Android—网络编程之Retrofit2整体结构了解以及+Okhttp3+rxjava2使用
Android—网络编程之Retrofit2源码分析
定义
Socket:网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。建立网络通信连接至少要一对端口号(socket)。socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口;HTTP提供了封装或者显示数据的具体形式;Socket提供了网络通信的能力。通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。
协议
socket是对TCP/IP的封装,TCP层用于数据的传输,分为TCP协议和UDP协议;IP层用于对网络主机的定位。Socket是TCP/IP协议的一个十分流行的编程界面,但是,Socket所支持的协议种类也不光TCP/IP一种。提供面向事务的简单不可靠信息传送服务。提供了无连接通信,且不对传送数据包进行可靠性保证,适合于一次传输少量数据,UDP传输的可靠性由应用层负责####
Socket也称为“套接字”,分为流式套接字和用户数据报套接字,分别对应于网络传输层的中的TCP和UDP协议。
- tcp协议:面向连接的协议,提供稳定的双向通信功能,需要3次握手
- udp协议:提供面向事务的简单不可靠信息传送服务。提供了无连接通信,且不对传送数据包进行可靠性保证,适合于一次传输少量数据,UDP传输的可靠性由应用层负责。
Socket通信流程
- Server端监听某一端口是否有连接请求
- Client端向服务端发起连接请求
- Server应答
- server端和Client 端都可以通过Send,Write等方法与对方通信。
相关类(资料引用)
-
Socket (TCP)
Socket 类实现了一个客户端 Socket,作为两台机器通信的终端,默认采用的传输层协议为 TCP 可靠传输协议。Socket 类除了构造函数返回一个 socket 外,还提供了 connect , getOutputStream, getInputStream 和 close 方法。connect 方法用于请求一个 socket 连接,getOutputStream 用于获得写 socket的输出流,getInputStream 用于获得读 socket 的输入流,close 方法用于关闭一个流。 -
DatagramSocket (UDP)
DatagramSocket 类实现了一个发送和接收数据报的 socket,传输层协议使用 UDP,不能保证数据报的可靠传输。DataGramSocket 主要有 send, receive 和 close 三个方法。send 用于发送一个数据报,Java 提供了 DatagramPacket 对象用来表达一个数据报。receive 用于接收一个数据报,调用该方法后,一直阻塞接收到直到数据报或者超时。close 是关闭一个 socket。 -
ServerSocket
ServerSocket 类实现了一个服务器 socket,一个服务器 socke t等待客户端网络请求,然后基于这些请求执行操作,并返回给请求者一个结果。ServerSocket 提供了 bind、accept 和 close 三个方法。bind 方法为ServerSocket 绑定一个IP地址和端口,并开始监听该端口。accept 方法为 ServerSocket 接受请求并返回一个 Socket 对象,accept 方法调用后,将一直阻塞直到有请求到达。close 方法关闭一个 ServerSocket 对象。 -
SocketAddress
SocketAddress 提供了一个 socket 地址,不关心传输层协议。这是一个虚类,由子类来具体实现功能、绑定传输协议。它提供了一个不可变的对象,被 socket 用来绑定、连接或者返回数值。 -
InetSocketAddress
InetSocketAddress 实现了IP地址的 SocketAddress,也就是有 IP 地址和端口号表达 Socket 地址。如果不制定具体的 IP 地址和端口号,那么 IP 地址默认为本机地址,端口号随机选择一个。 -
DatagramPacket(UDP)
DatagramSocket 是面向数据报 socket 通信的一个可选通道。数据报通道不是对网络数据报 socket 通信的完全抽象。socket通信的控制由DatagramSocket 对象实现。DatagramPacket 需要与 DatagramSocket 配合使用才能完成基于数据报的 socket 通信。
实例
两部分组成,客户端,服务端,客户端发送消息,服务端接收到消息以后回复,使用Socket通信
- 先看一下服务端
public class SocketServer extends Service{
private static boolean isDestory = false;
private static String[] reponse = new String[]{"hah","随机2","随机3","随机4","随机5","随机6","随机7"};
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
new Thread(new TcpServer()).start();
super.onCreate();
}
@Override
public void onDestroy() {
isDestory =true;
super.onDestroy();
}
private static class TcpServer implements Runnable {
@Override
public void run() {
ServerSocket serverSocket = null;
try {
//监听本地8866端口(端口可以随便设置,但不要占用系统端口)
serverSocket = new ServerSocket(8866);
Log.e( "serverSocket: ","服务已开启!!!" );
} catch (IOException e) {
e.printStackTrace();
}
while (!isDestory){
try {
final Socket client = serverSocket.accept();
Log.e( "serverSocketaccept: ","accept" );
new Thread(new Runnable() {
@Override
public void run() {
responseClient(client);
}
}).start();
}catch (Exception e){
e.printStackTrace();
}
}
}
private void responseClient(Socket client) {
BufferedReader bufferedReader = null;
PrintWriter printWriter=null;
try {
//字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取
bufferedReader = new BufferedReader(new InputStreamReader(client.getInputStream()));
//用来操作字符流。读取文本文件
printWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())), true);
printWriter.println("已连接。。欢迎来到服务端");
while (!isDestory){
String fromClient = bufferedReader.readLine();
if(fromClient==null){
break;
}
int i = new Random().nextInt(reponse.length);
String repons = reponse[i];
printWriter.println(repons);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(bufferedReader!=null){
bufferedReader.close();
}
}catch (Exception e){
e.printStackTrace();
}
try {
if(printWriter!=null){
printWriter.close();
}
}catch (Exception e1){
e1.printStackTrace();
}
try {
if(client!=null){
client.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
- 客户端(关键代码)
private void connectSocketServer() {
Socket clientSocket =null;
out = null;
while (clientSocket==null){
try {
clientSocket = new Socket("localhost", 8866);
mClientSocket = clientSocket;
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream())), true);
mHandler.sendEmptyMessage(SOCKET_CONNECT);
System.out.println("连接成功!");
} catch (IOException e) {
e.printStackTrace();
SystemClock.sleep(1000);
System.out.println("retry to connect...");
}
}
BufferedReader reader=null;
try {
reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
while (!MainActivity.this.isFinishing()){
String message = reader.readLine();
if(message!=null){
//用Handler携带将读取到的信息,通知列表更新
mHandler.obtainMessage(SOCKET_NEW_MESSAGE,message).sendToTarget();
}
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try{
if(reader!=null){
reader.close();
}
}catch (Exception e){
e.printStackTrace();
}
try {
if(out !=null){
out.close();
}
}catch (Exception e){
e.printStackTrace();
}
try {
if(clientSocket!=null){
clientSocket.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
//out是在 connectSocketServer()初始化的
out.println(sendMessage);
完整代码
##拼搏在技术道路上的一只小白And成长之路