JavaSocket短连接实现分别接收字符串和16进制数据
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了JavaSocket短连接实现分别接收字符串和16进制数据,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含7163字,纯文字阅读大概需要11分钟。
内容图文
![JavaSocket短连接实现分别接收字符串和16进制数据](/upload/InfoBanner/zyjiaocheng/741/0ec888910dff483bbe994fcce94d01b8.jpg)
做个笔记,在接收16进制数据的时候乱码了。原因是Socket在接收数据的时候需要根据不同的数据定义不同的接收方式,也就是约定好传输协议(具体体现在后面服务端接收16进制那里)。
字符串的发送接收
字符串发送:
字符串接收:
客户端代码:
没什么好说的,复制粘贴导包。
public static void main(String[] args)
{
try
{
Socket socket = new Socket("localhost", 8888);
//得到一个输出流,用于向服务器发送数据
OutputStream outputStream = socket.getOutputStream();
//将写入的字符编码成字节后写入一个字节流
OutputStreamWriter writer = new OutputStreamWriter(outputStream, "UTF-8");
System.out.println("请输入数据:");
while (true)
{
Scanner sc = new Scanner(System.in);
String data = sc.nextLine();
writer.write(data);
//刷新缓冲
writer.flush();
//只关闭输出流而不关闭连接
socket.shutdownOutput();
//获取服务器端的响应数据
//得到一个输入流,用于接收服务器响应的数据
InputStream inputStream = socket.getInputStream();
//字节流以UTF-8的编码转换为字符流
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
//为输入流添加缓冲
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
System.out.println("客户端IP地址:" + socket.getInetAddress().getHostAddress());
String info;
//输出服务器端响应数据
while ((info = bufferedReader.readLine()) != null)
{
System.out.println("收到来自服务端的信息:" + info);
}
//关闭资源
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
writer.close();
outputStream.close();
socket.close();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
服务端代码:
注意readLine()方法,客户端发送的内容结尾一定要有换行符,不然会一直阻塞导致客户端得不到响应。其它注释里都有。
try
{
System.out.println(">>>服务启动,等待终端的连接\n");
ServerSocket server = new ServerSocket(8888);
int count = 0;
while (true)
{
//开启监听
Socket socket = server.accept();
count++;
System.out.println(">>>第" + count + "个终端连接成功");
ServerThread thread = new ServerThread(socket);
thread.start();
}
}
catch (IOException e)
{
e.printStackTrace();
}
/**
* 短连接
*/
public class ServerThread extends Thread
{
private Socket m_socket;
public ServerThread(Socket socket)
{
this.m_socket = socket;
}
@Override
public void run()
{
//字节输入流
InputStream inputStream = null;
//字节输出流
OutputStream outputStream = null;
//字节输入流到字符输入流的转换
InputStreamReader inputStreamReader = null;
//加快字符读取速度
BufferedReader bufferedReader = null;
//打印输出流
PrintWriter printWriter = null;
try
{
inputStream = m_socket.getInputStream();
String info;
inputStreamReader = new InputStreamReader(inputStream);
bufferedReader = new BufferedReader(inputStreamReader);
//注意,readLine()方法如果没有读到报文结束符(换行)会一直阻塞
while ((info = bufferedReader.readLine()) != null)
{
System.out.println(">>>线程" + this.getId() + "收到来自终端的信息:" + info);
}
//关闭终端的输入流(不关闭服务端的输出流),此时m_socket虽然没有关闭,但是客户端已经不能再发送消息
m_socket.shutdownInput();
//解析终端的信息
String responseStr = "Null...";
if (null != info && !"".equals(info))
{
//模拟业务处理Thread.sleep(10000);
responseStr = new MessageReceive().RecevieHexStr(info);
}
outputStream = m_socket.getOutputStream();
printWriter = new PrintWriter(outputStream);
printWriter.write(responseStr);
printWriter.flush();
}
catch (Exception e)
{
e.printStackTrace();
}
//关闭资源
finally
{
System.out.println(">>>本次连接已断开\n");
try
{
if (printWriter != null)
printWriter.close();
if (outputStream != null)
outputStream.close();
if (bufferedReader != null)
bufferedReader.close();
if (inputStreamReader != null)
inputStreamReader.close();
if (inputStream != null)
inputStream.close();
if (m_socket != null)
m_socket.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
16进制数据的发送接收
客户端代码:无
由Socket测试工具来完成,网上大把,自行下载。
服务端代码:
开头说过使用Socket通信需要约定好协议,否则服务端不知道你客户端内容是否发送完毕,就会一直阻塞。前面的字符串的发送和接收其实也是有协议存在的,这个协议就是字符串和换行符,服务端读取的时候将字节流转为字符流,然后一行行的读取,读到换行符的时候就表示客户端的消息已发送完毕。
但是当客户端发送的是16进制数据的时候,这个时候服务端仍然用读取字符串的方式去处理就会乱码。所以这里采用的方法是将字节流以字节的形式一个一个的读出来,然后每个字节转为16进制的字符串。
byte[] bytes = new byte[1];
while ((dataInputStream.read(bytes)) != -1)
String tempStr = ConvertUtil.ByteArrayToHexStr(bytes);
同理,也需要一个标识符表示客户端的内容已经发送完毕,否则read()方法也会一直阻塞,导致客户端得不到响应。比如客户端发送内容的末尾加个7E,当服务端读到7E就跳出While循环,但前提是要保证发送内容里面7E是唯一的,如果有其它需要用7E表示的自行转义,然后服务端读取完内容以后再转义回来。
这里我使用的是另外一种方法判断客户端的内容是否发送完毕:InputStream对象的available()方法。
dataInputStream.available()
官方解释:返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。下一个调用可能是同一个线程,也可能是另一个线程。一次读取或跳过此估计数个字节不会受阻塞,但读取或跳过的字节数可能小于该数。大白话就是:返回剩余未读长度
至于其它的注释里都有写
/**
* 短连接
*/
public class ServerThread extends Thread
{
private Socket m_socket;
public ServerThread(Socket socket)
{
this.m_socket = socket;
}
@Override
public void run()
{
//字节输入流
InputStream inputStream = null;
//字节输出流
OutputStream outputStream = null;
//缓冲输入流
BufferedInputStream bufferedInputStream = null;
//数据输入流
DataInputStream dataInputStream = null;
//打印输出流
PrintWriter printWriter = null;
try
{
inputStream = m_socket.getInputStream();
String info = "";
bufferedInputStream = new BufferedInputStream(inputStream);
dataInputStream = new DataInputStream(bufferedInputStream);
//一次读取一个byte
byte[] bytes = new byte[1];
//注意,read()方法如果没有数据会一直阻塞,也就是永远不会等于-1,除非客户端调用close(),如果想在while循环外部获取数据则需要设定跳出条件
while ((dataInputStream.read(bytes)) != -1)
{
String tempStr = ConvertUtil.ByteArrayToHexStr(bytes) + " ";
info += tempStr;
//返回下次调用可以不受阻塞地从此流读取或跳过的估计字节数,如果等于0则表示已经读完
if (dataInputStream.available() == 0)
{
System.out.println(">>>终端信息读取完毕,最后一位:" + tempStr);
break;
}
}
System.out.println(">>>线程" + this.getId() + "收到来自终端的信息:" + info);
//关闭终端的输入流(不关闭服务端的输出流),此时m_socket虽然没有关闭,但是客户端已经不能再发送消息
m_socket.shutdownInput();
//解析终端的信息
String responseStr = "Null...";
//模拟业务处理
Thread.sleep(10000);
outputStream = m_socket.getOutputStream();
printWriter = new PrintWriter(outputStream);
printWriter.write(responseStr);
printWriter.flush();
}
catch (Exception e)
{
e.printStackTrace();
}
//关闭资源
finally
{
System.out.println(">>>本次连接已断开\n");
try
{
if (printWriter != null)
printWriter.close();
if (outputStream != null)
outputStream.close();
if (inputStream != null)
inputStream.close();
if (bufferedInputStream != null)
bufferedInputStream.close();
if (dataInputStream != null)
dataInputStream.close();
if (m_socket != null)
m_socket.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
自定义的转换类:
/**
* 普通byte[]转16进制Str
*
* @param array
*/
public static String ByteArrayToHexStr(byte[] array)
{
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < array.length; i++)
{
String hex = Integer.toHexString(array[i] & 0xFF);
if (hex.length() == 1)
{
stringBuilder.append("0");
}
stringBuilder.append(hex);
}
return stringBuilder.toString();
}
内容总结
以上是互联网集市为您收集整理的JavaSocket短连接实现分别接收字符串和16进制数据全部内容,希望文章能够帮你解决JavaSocket短连接实现分别接收字符串和16进制数据所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。