java socket通讯乱码问题的解决

java socket通讯乱码问题的解决使用socket通讯经常会遇到客户端、服务器端字符编码不一致的情况,如果传输的信息包含中文,这时我们可能就需要对传输的信息的按照指定的字符集进行解码或者编码首先我们了解jdkapi中的几个基本的概念String类StringpublicString(byte[] bytes,String charsetName)th

大家好,又见面了,我是你们的朋友全栈君。

使用socket通讯经常会遇到客户端、服务器端字符编码不一致的情况,如果传输的信息包含中文,这时我们可能就需要对传输的信息的按照指定的字符集进行解码

关于乱码的问题,最关键的要明白接受到的信息是什么编码的,就需要用什么字符集进行解码。

首先我们了解jdk api中的几个基本的概念

String类

String

public String(byte[] bytes,
              String charsetName)
       throws UnsupportedEncodingException

构造一个新的
String,方法是使用指定的字符集解码指定的字节数组。新的
String 的长度是一个字符集函数,因此不能等于字节数组的长度。

getBytes

public byte[] getBytes()

使用平台默认的字符集将此
String 解码为字节序列,并将结果存储到一个新的字节数组中。

getBytes

public byte[] getBytes(String charsetName)
                throws UnsupportedEncodingException

使用指定的字符集将此
String 解码为字节序列,并将结果存储到一个新的字节数组中。

在项目开发中遇到这种情况对方系统的编码为gb18030,而我们系统的编码为utf-8,两个系统直接使用socket进行通讯

在通讯过程中我们系统作为客户端需要按照gb18030进行报文发送,而当接受到对方系统的报文时我们需要将报文按照gb18030进行解码

具体测试代码如下:

socket服务端:

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class SocketServer {
    
    /**
     * @throws Exception
     */
    public void startServer(int port) throws Exception {
        ServerSocket serverSocket = new ServerSocket(port);
        Socket server = null;
        try {
            while (true) {
                server = serverSocket.accept();
                System.out.println("socket服务端启动……");
                try {
                    BufferedReader input = new BufferedReader(new InputStreamReader(new ByteArrayInputStream("服务端发给客户端的信息".getBytes())));
                    BufferedInputStream in = new BufferedInputStream(server.getInputStream());
                    PrintWriter out = new PrintWriter(new OutputStreamWriter(server.getOutputStream()));
                    
                    String serverstring = null;
                    String clientstring = null;
                    out.println("欢迎客户端连入");
                    out.flush();
                    while (true) {
                        byte[] buf = new byte[10000];
                        int size=0;
                        if ((size=in.read(buf))!=-1) {
                            clientstring = new String(buf,0,size,"GB18030");
                            if (clientstring != null) {
                                System.out.println("client:" + clientstring);
                            }
                        }    
                        serverstring = input.readLine();
                        out.println(serverstring);
                        out.flush();
                        break;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    server.close();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            serverSocket.close();
        }
    }
    
    public static void main(String[] args) {
        SocketServer ss = new SocketServer();
        int port = 8888;
        try {
            ss.startServer(port);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

socket客户端

 

import java.io.BufferedInputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;


public class SocketClient {
    
    /**
     * @throws Exception
     */
    public void makeConn(String ip, int port) throws Exception {
        Socket client = new Socket(ip, port);
        try {
//            BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
//            BufferedReader input = new BufferedReader(new InputStreamReader(new ByteArrayInputStream("客户端发给服务器端的信息".getBytes())));
            BufferedInputStream in = new BufferedInputStream(client.getInputStream());
            PrintWriter out = new PrintWriter(new OutputStreamWriter(client.getOutputStream(),"GB18030"));
            
            String clientString = null;
            String serverString = null;
            while (true) {
                byte[] buf = new byte[10000];
                int size=0;
                if ((size=in.read(buf))!=-1) {
                    serverString = new String(buf,0,size,"GB18030");
                    if (serverString != null) {
                        System.out.println("server:" + serverString);
                    }
                }
//                clientString = input.readLine();
                clientString = "客户端发给服务器端的信息";
                if (clientString != null) {
                    out.println(clientString);
                    out.flush();
                    break;
                }
            }
            in.close();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            client.close();
        }
    }
    
    public static void main(String[] args) {
        SocketClient sc = new SocketClient();
        int port = 8888;
        try {
            sc.makeConn("localhost", port);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

上述代码的关键在于以下几部分:

由于socket服务端的编码是gb18030的,因此在接受到socket服务端的报文后我们需要按照gb18030进行解码

clientstring = new String(buf,0,size,”GB18030″);

而socket客户端因为编码是utf-8的,而socket服务端只能识别gb18030的编码,所以socket客户端在发送报文时需要做转换

 PrintWriter out = new PrintWriter(new OutputStreamWriter(client.getOutputStream(),”GB18030″));

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/156985.html原文链接:https://javaforall.net

(0)
上一篇 2022年7月8日 下午12:00
下一篇 2022年7月8日 下午12:00


相关推荐

  • C++实现超分辨率 RDN

    C++实现超分辨率 RDNRDN(由残差密集网络实现的图像超分辨率)在《RDN-TensorFlow-master》有一个3倍模型(也只有这一个了):rdn_5_3_64_x3这里用C++实现这个的3倍重建:流程图:密集残差块:这个残差块结构内部和前面的ESRGAN(前面的文章)中的密集残差块是一样的,只是外部有点不同。定义密集残差块:struct密集残差块//4个卷积层…

    2022年6月18日
    29
  • 转:MFC之COleVariant[通俗易懂]

    转:MFC之COleVariant[通俗易懂]COleVariant本质上是一个枚举,用同一种类型来表达不同的子类型。如同boost中的variant。例子[cpp]viewplaincopyCOleVariantvar(3.6f);floatv=var.fltVal;CStringstr(“testCOleVariant”);COleVariantvar2(st…

    2022年7月18日
    16
  • 国产AI再突破!月之暗面Kimi K2Thinking开源,460万美元成本力压GPT-5?

    国产AI再突破!月之暗面Kimi K2Thinking开源,460万美元成本力压GPT-5?

    2026年3月12日
    2
  • wpa_supplicant 框架

    wpa_supplicant 框架1 系统架构 AndroidWiFi 系统引入了 wpa supplicant 它的整个 WiFi 系统以 wpa supplicant 为核心来定义上层用户接口和下层驱动接口 整个 WiFi 系统架构如下图所示 1 1WifiService 由 SystemServer 启动的时候生成的 Connecttivit 创建 负责启动关闭 wpa supplicant 启动和关闭 WifiMonitor 线程 把命令下发给 wpa supplicant 以及更新 WIFI 的状态 处理其它模块通过 IWifiManager 接

    2026年3月18日
    4
  • 直通线和交叉线的使用(网线)

    直通线和交叉线的使用(网线)原文:http://blog.sina.com.cn/s/blog_62c179fd0100sefl.html关于网络设备的定义和设备间连接方式一般规律: 第一,你需要了解两类设备:DTE类设备和DCE类设备。DTE类设备:PC、路由器、交换机uplink口、HUB级联口DCE类设备:交换机普通口、HUB普通口   同类设备间相连使用交叉线方式;异类设备间相

    2022年6月19日
    30
  • Linux cp命令详解

    Linux cp命令详解Linux 中使用 cp 命令复制文件 夹 本文就日常工作中常用的 cp 命令整理如下 一 复制一个源文件到目标文件 夹 命令格式为 cp 源文件目标文件 夹 这个是使用频率最多的命令 负责把一个源文件复制到目标文件 夹 下 如下图所示 复制到文件夹下 则文件名保持不变 复制到文件中 则文件名变更 如果目标文件已经存在或目标文件夹中含有同名文件 则复制之后目标文件或目标文件夹中的同名文件会被覆盖 cp

    2026年3月17日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号