开发环境:
客户端:java myEclipse8.5
服务端:c# vs2008
此例子内java 代码来自 http://blog.csdn.net/xd1210aaa/article/details/7074459
java 与 c#是两种完全不同实现机制的语言,但是可以通过socket作为桥梁,做相应的沟通,本例为大家展示,如何编写java c#之间进行通信。
此技术点本没有什么难度可言,但在笔者实践的过程中发现java 与c#的utf-8编码格式的显示方式上有一定区别。所以造成中文乱码。花了2个小时左右写了一种算法,虽然不怎么灵巧,而且可能会影响程序性能,但是可以解决乱码问题,特在此注明,若为追求程序性能,tcpip包内只用发单字节就可以了,这样简单的发送可以处理两种语言通讯时产生的事件,从而实现java端调用c#端相应的方法,或相反,若要实现聊天类似的功能(包括中文),则需要使用此算法。
以下java代码,改动send方法
public String send(String msg)
{
try {
System.out.println("发送的内容:" + msg);
PrintWriter out = new PrintWriter(socket.getOutputStream());
byte[] b = msg.getBytes("UTF-8");
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < b.length; i++) {
buffer.append(b[i]+256).append(",");
}
out.print(buffer.toString());
out.flush();
return null;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
大家是否注意到,b[i] + 256 ,
这是因为在java中,byte型是有符号的,取值范围在-128 到127,而c#的byte型则是0-255,无符号型,在此需要对byte进行转换,转为c#可识别的byte编码,b[i]+256则可以实现效果。付下图,c# 与 java 不同的utf-8表示形式,汉字“呵呵”;
以下为c#端代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
namespace AndroidAndCSharp
{
public partial class Form1 : Form
{
//监听对象
Socket listener;
private const int PORT = 9758; //监听端口
private static IPAddress IP; //本地网卡地址
public Form1()
{
InitializeComponent();
//获取本地网卡地址
IP = Form1.GetIP();
//实例化监听对象
listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//启动线程
backgroundWorker1.RunWorkerAsync();
}
/// <summary>
/// 获取本地网卡地址
/// </summary>
/// <returns></returns>
public static System.Net.IPAddress GetIP()
{
System.Net.IPAddress ip = System.Net.IPAddress.Parse("127.0.0.1");
System.Net.IPHostEntry host = System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName());
foreach (System.Net.IPAddress item in host.AddressList)
{
if (item.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
return item;
}
}
//如果没有找到可用地址,则用回环地址
return ip;
}
/// <summary>
/// 多线程控件 , 当线程开始时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
EndPoint ip = new IPEndPoint(Form1.IP, Form1.PORT);
//监听绑定好的ip与端口
listener.Bind(ip);
//设置缓冲区大小,单位为字节
listener.ReceiveBufferSize = 100;
//挂起连接的最大长度
listener.Listen(10);
while(true)
{
//开始监听,并等待数据
Socket socket = listener.Accept();
byte[] buffer = new byte[100];
socket.Receive(buffer);
//线程向外部发送报告
backgroundWorker1.ReportProgress(1 , buffer);
socket.Close();
}
}
/// <summary>
/// 多线程控件,当线程向外发出报告时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//从线程内部获取附加参数
byte[] b = (byte[])e.UserState;
byte[] buffer = new byte[b.Length];
string[] str = new string[b.Length];
for (int i = 0,j = 0; i < b.Length; i++)
{
//去掉缓冲区内未使用的空间
if (b[i] != 0)
{
//不为逗号
if (b[i] != 44)
{
str[j] += (char)b[i];
}
else
{
j++;
}
}
else
{
break;
}
}
for (int i = 0; i < str.Length; i++)
{
//不对缓冲区内垃圾区域做处理
if (str[i] != null)
{
buffer[i] = Convert.ToByte(str[i]);
}
else
{
break;
}
}
//把转换后的c#可识别编码字节数组转为字符串
string msg = Encoding.UTF8.GetString(buffer);
textBox1.Text = msg;
}
}
}
在backgroundWorker1_ProgressChanged方法中,对java 端发来的字符进行处理,转为c#可识别并有效的转为string的算法。
请注意,c#在设置监听时,需要获取本地网卡地址。
程序运行结果
![](http://hi.csdn.net/attachment/201112/16/0_13240292012rMF.gif)