Socket通讯
socket分为UDP和TCP两种协议
可以建立长连接socket和短链接socket 区别在于不关闭socket 多次发送和发送一次后关闭socket
UDP建立socket:
// 服务端
DatagramSocket ds = new DatagramSocket(9090);
// 客户端
byte[] data = new byte[10];
// 获取本机ip
InetAddress localHost = InetAddress.getLocalHost();
new DatagramPacket(data,0,data.length,localHost,9090);
TCP建立socket:
// 服务端
ServerSocket ss = new ServerSocket(9090);
// 客户端
Socket socket = new Socket("127.0.0.1",9090);
TCP 客户端Demo
public static void main(String[] args) {
Socket s = null;
String testData = "测试数据";
try {
s = new Socket("127.0.0.1",9090);
OutputStream outputStream = s.getOutputStream();
// 根据业务自定义编码
outputStream.write(testData.getBytes("GBK"));
InputStream inputStream = s.getInputStream();
// 读取服务端响应
String read = read(inputStream);
log.info("客户端收到的数据:"+read);
} catch (IOException e) {
e.printStackTrace();
}finally{
if(null != outputStream){
try{
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(null != inputStream){
try{
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(null != s ){
try {
s.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
TCP 服务端Demo
public static void main(String[] args) {
ServerSocket ss = null;
try{
ss = new ServerSocket(9090);
while (true){
// 阻塞等待客户端链接
Socket accept = ss.accept();
OutputStream os = null;
InputStream is = null;
try {
os = accept.getOutputStream();
is = accept.getInputStream();
// 读取客户端的数据
String message = read(is);
String mes = "";
if(null == message){
mes = "数据接收失败";
log.error("数据接收失败!");
}else{
// 业务逻辑
mes = "业务处理完成";
}
// 响应给客户端的数据
os.write(mes.getBytes("GBK"));
accept.close();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
log.error("error:",e);
} finally {
if(null != is){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(null != os){
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}catch (IOException e){
e.printStackTrace();
log.error("error:",e);
}finally {
if(null != ss ){
try {
ss.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
读取数据
public static String read(InputStream inputStream) throws IOException{
if(null == inputStream){return null;}
String data = "";
try{
// 读取报文内容这里写死1024 正常传输数据会约定数据长度
byte[] bys = new byte[1024];
int len = inputStream.read(bys);
data = new String(bys, "GBK");
}catch (Exception e){
e.printStackTrace();
log.error("读取数据异常",e);
}
//输出数据
return data;
}
接收数据不全处理
public static synchronized String read(InputStream inputStream) throws IOException, InterruptedException {
if(null == inputStream){return null;}
int countRead = 0;
int dataLengthByte = 8;
// 获取前8位数据长度
byte[] bys = new byte[dataLengthByte];
int len;
len = inputStream.read(bys);
countRead +=len;
String dataLength = new String(bys, "GBK");
int i ;
try{
i = Integer.parseInt(dataLength.trim());
}catch (NumberFormatException e){
log.error("异常数据无法解析!略过:【"+dataLength+"】");
return null;
}
log.info("数据长度:"+i);
boolean successFlag = true;
String data = "";
try{
if(i == 0){return null;}
i -= dataLengthByte;
if(i < 0){return null;}
// 读取报文内容
bys = new byte[i];
len = inputStream.read(bys);
countRead += len;
data = new String(bys, "GBK");
if(countRead != i+dataLengthByte ){
log.error("数据接收不完整继续接收!");
successFlag = false;
// 数据接收不完整继续接收
int initLoop = 0;
int maxLoop = 10;
while(initLoop < maxLoop){
Thread.sleep(1000);
len = inputStream.read(bys,countRead-dataLengthByte,i-(countRead-dataLengthByte));
countRead += len;
log.error("第"+(initLoop+1)+"次继续接收,接收长度:"+len+"数组长度:"+bys.length+" 报文内容长度:"+i);
if(countRead == i+dataLengthByte){
data = new String(bys, "GBK");
successFlag = true;
log.error("续接成功!");
// 接收成功
break;
}
initLoop ++;
}
}
}catch (Exception e){
e.printStackTrace();
log.error("读取数据异常",e);
}
//输出数据
return successFlag?dataLength.concat(data):null;
}
踩过的坑
读取流内容 和写入流内容的方式有很多
比如 :DataOutputStream
DataOutputStream.writeUTF();方法写入的内容 接收也同样要使用DataInputStream的readUTF();
使用inputStream的read()方法是收不到数据的。