客户端使用java,服务器端使用的是C#。两者之间使用基于TCP的Socket通信方式。可是,做了一个测试小例子,结果从客户端传过来的都是乱码。于是上网查,希望可以找到解决方法,可是,网上有好多的答案,经过了很多的实验,都不能很好的解决。没办法只能靠自己一点一点的排查了。
经过一番努力,最终找到了原因:C#和java的编码方式不同。虽然找到了原因,但是网上关于这个问题的答案也是百家争鸣,在这里就给出源代码,希望对大家有帮助。
首先是客户端的java代码(这是比较简单的部分)
import java.net.*;
import java.io.*;
public class TCPCline{
public static void main(String[] args) throws Exception{
try{
//这里的IP地址是服务器的IP地址,端口号和服务器统一
Socket s = new Socket("IP地址",端口);
OutputStream os = s.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
String sendStr = "你好!hello";
//注意这里,getBytes()中的"UTF-8"
byte[] bs = sendStr.getBytes("UTF-8");
//这里使用的是write(),不是writeUTF(),至于为什么,可以查看java帮助文档,里面讲解了
dos.write(bs,0,bs.length);
//这里没有使用下面两句,是因为,当我们关闭客户端的时候,在服务器端也可以记录是哪一个客户端掉线了
//dos.close();
//s.close();
}catch(ConnectException connExc){
connExc.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
}
}
C#的服务器端代码,在这里说明一下,我们把服务器端的代码放到了一个类库TCPServer中,下面是错误日志类代码(客户端发送的消息,以及掉线通知都放到这里)
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System;
namespace TCPServer
{
///
/// 错误日志类
///
public class LogHelper
{
public static readonly object objLock = new object();
///
/// 将错误写入.log文件下
///
/// 错误信息
/// 异常
public static void Err(string msg, Exception ex)
{
string s = "";
if (ex != null)
{
s = "err:" + msg + ":" + ex.Message;
}
else
{
s = msg ;
}
//将错误输出到log文件中
string filename = AppDomain.CurrentDomain.BaseDirectory + "log/" + Convert.ToString(getUnixTime()) + ".log";
lock (objLock)
{
using (System.IO.StreamWriter sw = new System.IO.StreamWriter(filename, true))
{
sw.WriteLine(s);
if (ex != null)
{
sw.WriteLine(ex.StackTrace);
}
sw.WriteLine("time:" + DateTime.Now.ToString());
sw.WriteLine("----------------------------------");
}
}
} ServerListen类
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System;
namespace TCPServer
{
public class ServerListen
{
public static void Run(Object iGetClientData)
{
IPEndPoint serverIP = new IPEndPoint(IPAddress.Parse("IP地址"), 端口);//本机预使用的IP和端口
Socket skServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
skServer.Bind(serverIP);
skServer.Listen(100);//连接客户端的上限
while (true)
{
Socket skClient;
try
{
//当有可用的客户端连接尝试时执行,并返回一个新的socket,用于与客户端之间的通信
skClient = skServer.Accept();
}
catch (Exception ex)
{
LogHelper.Err("接收用户连接失败 ServerListen.Run Socket.Accept", ex);
continue;
}
ThrClient thrC = new ThrClient(skServer, skClient, (IGetClientData)iGetClientData);
Thread t = new Thread(thrC.Run);
t.Start();
}
}
}
} ThrClient类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace TCPServer
{
public class ThrClient
{
private static readonly StringBuilder sb = new StringBuilder();
private Socket skServer;
private Socket skClient;
private IPEndPoint clientIP;
private IGetClientData iGetClientData;
//每次接收发送的临时信息
private byte[] sendData;//发送的信息
private byte[] receiveData = new byte[1024];//接收信息
private int receiveN;
private int netID;
///
/// ThrClient构造方法
///
/// 服务端
/// 客户端
public ThrClient(Socket pSkServer, Socket pSkClient,IGetClientData iGetClientData)
{
this.skServer = pSkServer;
this.skClient = pSkClient;
this.iGetClientData = iGetClientData;
this.clientIP = (IPEndPoint)this.skClient.RemoteEndPoint;
//下面一定要使用UTF8而不能使用Uncode
this.sendData = Encoding.UTF8.GetBytes("success");
try
{
this.skClient.Send(sendData, sendData.Length, SocketFlags.None);//发送信息
}
catch (Exception ex)
{
LogHelper.Err("发送第一次连接成功信息 ThrClient.ThrClient Socket.Send", ex);
}
}
public void Run()
{
while (true)
{
try
{
this.receiveN = skClient.Receive(this.receiveData);//接收
if (this.receiveN != 0)
{
string removeMsg = Encoding.UTF8 .GetString(receiveData, 0, receiveN);
iGetClientData.getThread(removeMsg);
}
}
catch (Exception ex)
{
iGetClientData.getClientIP(((IPEndPoint)skClient.RemoteEndPoint).Address);
break;
}
}
}
} 两种语言之间的通信问题真的是挺令人头疼的,我们这也是通过猜测然后多次实验才找到了答案。所以,就像《大话设计模式》中提到的,不痴迷,不成功。