TCP与UDP的区别
TCP 和UDP都是传输层的协议, 但TCP是面向连接、可靠的字节流服务,传输速度慢,而UDP是用户数据报协议,是一种面向数据报的协议,不需要建立连接,传输速度快。
对于TCP要经过3次握手:
第一次握手:请求端发送一条消息到服务端,服务端收到消息。ack
第二次握手:接收端接收到消息后发送一条消息给请求端,表示服务端已经收到了消息 ack <–>syn+1
第三次握手:请求端接收到服务端返回的消息,证明建立了连接,才开始传输数据 ack <—>ack+1
何为连接:双方记录双方的信息(ip和port)
连接与线程无关,所以不应把连接放在线程了执行,否则线程挂掉会导致连接挂掉。
UDP编程
接收方创建步骤:
- 创建一个DatagramSocket对象,并指定监听的端口号
DatagramSocket socket = new DatagramSocket (4567); - 创建一个byte数组用于接收
byte data[] = new byte[1024]; - 创建一个空的DatagramPackage对象
DatagramPackage package = new DatagramPackage(data , data.length); - 使用receive方法接收发送方所发送的数据,同时这也是一个阻塞的方法
socket.receive(package); - 得到发送过来的数据
new String(package.getData() , package.getOffset() , package.getLength());
发送方创建步骤:
- 创建一个DatagramSocket对象
DatagramSocket socket = new DatagramSocket (4567); - 创建一个 InetAddress , 相当于是地址
InetAddress serverAddress = InetAddress.getByName(“想要发送到的那个IP地址”); - 这是随意发送一个数据
String str = “ok”; - 转为byte类型
byte data[] = str.getBytes(); - 创建一个DatagramPacket 对象,并指定要讲这个数据包发送到网络当中的哪个地址,以及端口号
DatagramPacket package = new DatagramPacket (data , data.length , serverAddress , 4567); - 调用DatagramSocket对象的send方法 发送数据
socket . send(package);
UDPClient代码
package com.ldc.materialdesign.udp;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
/**
* Created by AA on 2017/1/4.
*/
public class UDPClient {
private static final int SERVER_PORT = 6000;//端口
private DatagramSocket dSocket = null;
private ISocketResponse mISocketResponse = null;
public UDPClient(ISocketResponse mISocketResponse) {
super();
this.mISocketResponse = mISocketResponse;
}
public String send(String ip, int port, String msg) {
StringBuilder sb = new StringBuilder();
InetAddress local = null;
try {
local = InetAddress.getByName(ip); // 本机测试
sb.append("已找到服务器,连接中...").append("\n");
} catch (UnknownHostException e) {
sb.append("未找到服务器.").append("\n");
e.printStackTrace();
}
try {
dSocket = new DatagramSocket(); // 注意此处要先在配置文件里设置权限,否则会抛权限不足的异常
sb.append("正在连接服务器...").append("\n");
} catch (SocketException e) {
e.printStackTrace();
sb.append("服务器连接失败.").append("\n");
}
int msg_len = msg == null ? 0 : msg.length();
DatagramPacket dPacket = new DatagramPacket(msg.getBytes(), msg_len,
local, port);
try {
dSocket.send(dPacket);
sb.append("消息发送成功!").append("\n");
dSocket.receive(dPacket);
mISocketResponse.onSocketResponse(dPacket.getData());
} catch (IOException e) {
e.printStackTrace();
sb.append("消息发送失败.").append("\n");
}
dSocket.close();
return sb.toString();
}
}
UDPServer代码
package com.ldc.materialdesign.udp;
import android.util.Log;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
/**
* Created by AA on 2017/1/4.
*/
public class UDPServer implements Runnable{
private static final int PORT = 6000;
private byte[] msg = new byte[1024];
private boolean life = true;
public UDPServer() {
}
public boolean isLife() {
return life;
}
public void setLife(boolean life) {
this.life = life;
}
@Override
public void run() {
DatagramSocket dSocket = null;
DatagramPacket dPacket = new DatagramPacket(msg, msg.length);
try {
dSocket = new DatagramSocket(PORT);
while (life) {
try {
dSocket.receive(dPacket);
Log.i("UDPServer", new String(dPacket.getData()));
dPacket.setData("ok".getBytes());
dSocket.send(dPacket);
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (SocketException e) {
e.printStackTrace();
}
}
}
调用先开启Server再发送数据报
// 开启服务器
ExecutorService exec = Executors.newCachedThreadPool();
UDPServer server = new UDPServer();
exec.execute(server);
// 发送消息
send_bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
UDPClient client = new UDPClient(new ISocketResponse() {
@Override
public void onSocketResponse(byte[] responseData) {
Log.e("onSocketResponse", new String(responseData));
}
});
Log.e("client",client.send("localhost",6000,msg_et.getText().toString()));
}
}).start();
}
});
TCP编程
TCP的客户端
例如:tcp抄读电表数据的例子
1. 打开客户端、连接服务端
tcpnioClient = new TCPNIOClient(this.getApplicationContext(), socketListener, "59.39.7.155", 9600);
tcpnioClient.open();
- 登录通信服务器
String temp = ProtocolCommunicationServer.frame_login(terminalAddr);
socketData.packetData(StringUtils.HexStringToByteArray(temp));
tcpnioClient.sendData(socketData);
- 连接终端
String temp = ProtocolCommunicationServer.frame_queryIfCanEstablishConnection(terminalAddr);
sendData(temp);
- 抄读数据
if (datas.size()>0){
sendData(datas.get(0));
datas.remove(0);
}
- 断开连接终端
String disconnectStr = ProtocolCommunicationServer.frame_disconnectServer(terminalAddr);
sendData(disconnectStr);
- 登出通信服务器
String logout = ProtocolCommunicationServer.frame_logout(terminalAddr);
sendData(logout);