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″));

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 云服务器搭建青龙面板每日自动拿京豆

    云服务器搭建青龙面板每日自动拿京豆前言:之前网上有只要扫码一下就可以每天领上百京豆和一些红包的活动,后来呢,扫码就失效了,但是呢,这背后的技术还没有失效。这白嫖活动其实就是用脚本代替我们去参与京东的各种活动,去获取红包和京豆,而这些脚本是部署在电脑上,定时去执行的,接下来,根据网上的大佬的教程,我们也来实现一下。每天100-200京豆不等,坐收渔利,快来试试吧。一、安装前的准备​青龙面板是使用Docker来安装的,理论上,只要有可以运行Docker的电脑都可以进行安装。但是呢,因为脚本要定时运行,所以最好安装在服务器上,或

    2022年10月14日
  • 走进音视频的世界——Matroska封装格式的介绍(二)「建议收藏」

    走进音视频的世界——Matroska封装格式的介绍(二)「建议收藏」Matroska封装格式非常灵活、兼容性好,既适用于本地文件存储又可以进行实时流传输。本篇文章主要探讨Matroska的编解码器映射,如何封装视频流、音频流、字幕流。如果要Matroska的介绍、功能和基本结构,请查看上一篇文章:走进音视频的世界——Matroska封装格式的介绍(一)。一、Matroska流Matroska有两种传输流:文件访问(存储)和实时流传输(直播)。1.文件存储Matroska是一种容器,支持把多媒体流封装成为文件,存储于本地。Matroska的开销很小,非常适合

  • 散列_双重散列

    散列_双重散列散列

  • 纯HTML个人简历模板代码

    纯HTML个人简历模板代码<html><bodybackground=http://p1.so.qhmsg.com/t01ed5a885549b6bf3b.jpg><tableborder=”1″align=”center”cellpadding=”10″width=”800″><tr><thcolspan=”7″bgcolor=”B…

  • kit中文_flask和django的对比

    kit中文_flask和django的对比#介绍ImageKit是用于处理图像的Django应用程序。如果需要从原图上生成一个长宽为50×50的图像,则需要ImageKit。ImageKit附带了一系列图像处理器,用于调整大小和裁剪等常见

  • 归一化函数normalize详解_求归一化常数A

    归一化函数normalize详解_求归一化常数A1.归一化归一化就是要把需要处理的数据经过处理后(通过某种算法)限制在你需要的一定范围内。首先归一化是为了后面数据处理的方便,其次是保证程序运行时收敛加快。归一化的具体作用是归纳统一样本的统计分布性。归一化在0-1之间是统计的概率分布,归一化在某个区间上是统计的坐标分布。归一化有同一、统一和合一的意思。归一化的目的,是使得没有可比性的数据变得具有可比性,同时又保持相比较的两个数据之间的相对关系,……

    2022年10月11日

发表回复

您的电子邮箱地址不会被公开。

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