Socket 作为一种通用的技术规范,首次是由 Berkeley 大学在 1983 为 4.2BSD Unix 提供的,后来逐渐演化为 POSIX 标准。Socket API 是由操作系统提供的一个编程接口,让应用程序可以控制使用 socket 技术。
Socket API 不属于 TCP/IP协议簇,只是操作系统提供的一个是一个对 TCP / IP协议进行封装 的编程调用接口,工作在应用层与传输层之间:
一个 Socket 包含两个必要组成部分:
地址:IP 和端口号组成一队套接字
协议:Socket 所用的是传输层协议,目前有 TCP、UDP、raw IP
协议
根据传输方式不同(即使用的协议不同)可分为三种:
1.Stream Sockets(流套接字)
基于 TCP协议,采用 流的方式 提供可靠的字节流服务。TCP 协议有以下特点:
面向连接:指的是要使用TCP传输数据,必须先建立TCP连接,传输完成后释放连接,就像打电话一样必须先拨号建立一条连接,打完后挂机释放连接。
全双工通信:即一旦建立了TCP连接,通信双方可以在任何时候都能发送数据。
可靠的:指的是通过TCP连接传送的数据,无差错,不丢失,不重复,并且按序到达。
面向字节流:流,指的是流入到进程或从进程流出的字符序列。简单来说,虽然有时候要传输的数据流太大,TCP报文长度有限制,不能一次传输完,要把它分为好几个数据块,但是由于可靠性保证,接收方可以按顺序接收数据块然后重新组成分块之前的数据流,所以TCP看起来就像直接互相传输字节流一样,面向字节流。
2.Datagram Sockets(数据报套接字)
基于 UDP协议,采用 数据报文 提供数据打包发送的服务。UDP 协议有以下特点:
无连接的:和TCP要建立连接不同,UDP传输数据不需要建立连接,就像写信,在信封写上收信人名称、地址就可以交给邮局发送了,至于能不能送到,就要看邮局的送信能力和送信过程的困难程度了。
不可靠的:因为UDP发出去的数据包发出去就不管了,不管它会不会到达,所以很可能会出现丢包现象,使传输的数据出错。
面向报文:数据报文,就相当于一个数据包,应用层交给UDP多大的数据包,UDP就照样发送,不会像TCP那样拆分。
没有拥塞控制:拥塞,是指到达通信子网中某一部分的分组数量过多,使得该部分网络来不及处理,以致引起这部分乃至整个网络性能下降的现象,严重时甚至会导致网络通信业务陷入停顿,即出现死锁现象,就像交通堵塞一样。TCP建立连接后如果发送的数据因为信道质量的原因不能到达目的地,它会不断重发,有可能导致越来越塞,所以需要一个复杂的原理来控制拥塞。而UDP就没有这个烦恼,发出去就不管了。
3.Row Sockets
通常用在路由器或其他网络设备中,这种 socket 不经过TCP/IP协议簇中的传输层(transport layer),直接由网络层(Internet layer)通向应用层(Application layer),所以这时的数据包就不会包含 tcp 或 udp 头信息。
进入主题
public class MainActivity2 extends AppCompatActivity {
//结束标识符
private String TAILED = "HUSHUAIKANGEND";
private ServiceConnection sc;
private Button bnt;
private EditText edit;
private Socket socket;
private int j;
private InputStream is;
private InputStreamReader isr;
private Handler handler = new Handler() {
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 545:
edit.setText(null);
break;
case 546:
Toast.makeText(MainActivity2.this, "链接断开", Toast.LENGTH_SHORT).show();
edit.setText(null);
break;
}
}
};
private boolean connected;
private OutputStream outputStream;
private int o;
private ArrayList<String> strings;
private int i1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
strings = new ArrayList<>();
initSocket();
}
private void initSocket() {
//配置IP以及port,记得更换IP
initView("127.0.0.0", 30002);
}
private void initView(String ip, int port) {
new Thread(() -> {
try {
//进行链接
socket = new Socket(ip, port);
//判断是否链接
connected = socket.isConnected();
if (!connected){
releaseSocket(false);
}
try {
//c创建二进制输入输出流
DataInputStream in = new DataInputStream(this.socket.getInputStream());
DataOutputStream out = new DataOutputStream(this.socket.getOutputStream());
OutputStream os = socket.getOutputStream();
while (true) {
try {
//制定一次长度
DataInputStream socketReader = new DataInputStream(in);
int bufferSize = 1024 * 1024;
byte[] bytes = new byte[bufferSize];
socketReader.read(bytes);
String str = new String(bytes);
str = str.trim();
String data = str;
//截取数据
Log.e("TAG", "数据==" + data);
SENF(data, os);
} catch (IOException e) {
// 连接被断开(被动)
} catch (Exception e) {
}
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
e.printStackTrace();
}
}).start();
}
/*释放资源*/
private void releaseSocket(boolean ifan) {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
outputStream = null;
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
}
socket = null;
}
if (!ifan) {
initSocket();
}
}
private void SENF(String str, OutputStream os) {
try {
Log.d("Log", "连接HUSHUAIK==" + str);
String temp = "";
String end = "HUSHUAIKANGEND";
temp = temp + str;
if (str.length() < 14) {
return;
}
//验证拼接数据是否完整
String d = new String(str.substring(str.length() - 14));
//拼接数据完整打印数据并清除临时数据
if (d.equals(end)) {
temp = temp.replace("HUSHUAIKANGEND", "");
JSONObject jsonObject2 = new JSONObject(temp);
if (jsonObject2.optString("type") == null || jsonObject2.optString("type").equals("") || jsonObject2.optString("type").equals("[]")) {
return;
}
JSONObject jsonObject1 = new JSONObject(str);
if (jsonObject1.optString("type").equals("client_id")) {
try {
String data = AESUtilsnew.encrypt(AesUtils.generateKey(), jsonObject1.optString("client_id"));
JSONObject jsout2 = new JSONObject();
jsout2.put("type", "auth");
jsout2.put("token", data);
jsout2.put("user", 3);
PrintWriter pw = new PrintWriter(os);
pw.write(jsout2 + "HUSHUAIKANGEND");
pw.flush();
} catch (Exception e) {
}
}
}
} catch (Exception e) {
}
}
}
点运行即可:
07-15 17:48:22.689 14080-14105/com.example.myapplication E/TAG: 数据=={"type":"client_id","client_id":"7f000001754e0000824e"}HUSHUAIKANGEND
07-15 17:48:22.858 14080-14105/com.example.myapplication E/TAG: 数据=={"code":200,"msg":"认证成功","type":"auth"}HUSHUAIKANGEND
07-15 17:48:23.905 14080-14105/com.example.myapplication E/TAG: 数据=={"type":"cnc_status","hardware":"F0049148","status":"待机"}HUSHUAIKANGEND