tcp/ip通讯

最近正在做一个项目,其中遇到了一个问题就是java与.NET之间的通信问题。具体的问题是这样的:

        客户端使用java,服务器端使用的是C#。两者之间使用基于TCP的Socket通信方式。可是,做了一个测试小例子,结果从客户端传过来的都是乱码。于是上网查,希望可以找到解决方法,可是,网上有好多的答案,经过了很多的实验,都不能很好的解决。没办法只能靠自己一点一点的排查了。

        经过一番努力,最终找到了原因:C#和java的编码方式不同。虽然找到了原因,但是网上关于这个问题的答案也是百家争鸣,在这里就给出源代码,希望对大家有帮助。

首先是客户端的java代码(这是比较简单的部分)

  1. import java.net.*;  
  2. import java.io.*;  
  3.   
  4. public class TCPCline{  
  5.     public static void main(String[] args) throws Exception{  
  6.         try{  
  7.             //这里的IP地址是服务器的IP地址,端口号和服务器统一   
  8.             Socket s = new Socket("IP地址",端口);  
  9.             OutputStream os = s.getOutputStream();  
  10.             DataOutputStream dos = new DataOutputStream(os);  
  11.               
  12.             String sendStr = "你好!hello";              
  13.             //注意这里,getBytes()中的"UTF-8"   
  14.             byte[] bs = sendStr.getBytes("UTF-8");  
  15.              //这里使用的是write(),不是writeUTF(),至于为什么,可以查看java帮助文档,里面讲解了   
  16.             dos.write(bs,0,bs.length);  
  17.             //这里没有使用下面两句,是因为,当我们关闭客户端的时候,在服务器端也可以记录是哪一个客户端掉线了     
  18.             //dos.close();   
  19.             //s.close();   
  20.             }catch(ConnectException connExc){  
  21.                 connExc.printStackTrace();    
  22.                   
  23.             }catch(IOException e){  
  24.                 e.printStackTrace();  
  25.             }  
  26.     }  
  27. }  
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

下面是错误日志类代码(客户端发送的消息,以及掉线通知都放到这里

  1. using System.Collections.Generic;  
  2. using System.Linq;  
  3. using System.Text;  
  4. using System;  
  5.   
  6. namespace TCPServer  
  7. {  
  8.     /// <summary>   
  9.     /// 错误日志类   
  10.     /// </summary>   
  11.     public class LogHelper  
  12.     {  
  13.         public static readonly object objLock = new object();  
  14.        /// <summary>   
  15.        /// 将错误写入.log文件下   
  16.        /// </summary>   
  17.        /// <param name="msg">错误信息</param>   
  18.        /// <param name="ex">异常</param>   
  19.         public static void Err(string msg, Exception ex)  
  20.         {  
  21.             string s = "";  
  22.             if (ex != null)  
  23.             {  
  24.                 s = "err:" + msg + ":" + ex.Message;  
  25.             }  
  26.             else  
  27.             {  
  28.                s = msg ;  
  29.             }  
  30.             //将错误输出到log文件中   
  31.             string filename = AppDomain.CurrentDomain.BaseDirectory + "log/" + Convert.ToString(getUnixTime()) + ".log";  
  32.             lock (objLock)  
  33.             {  
  34.                 using (System.IO.StreamWriter sw = new System.IO.StreamWriter(filename, true))  
  35.                 {  
  36.                     sw.WriteLine(s);  
  37.                     if (ex != null)  
  38.                     {  
  39.                         sw.WriteLine(ex.StackTrace);  
  40.                     }  
  41.                      
  42.                     sw.WriteLine("time:" + DateTime.Now.ToString());  
  43.                     sw.WriteLine("----------------------------------");  
  44.                 }  
  45.             }  
  46.         }  
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System;

namespace TCPServer
{
    /// <summary>
    /// 错误日志类
    /// </summary>
    public class LogHelper
    {
        public static readonly object objLock = new object();
       /// <summary>
       /// 将错误写入.log文件下
       /// </summary>
       /// <param name="msg">错误信息</param>
       /// <param name="ex">异常</param>
        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类

  1. using System.Collections.Generic;  
  2. using System.Linq;  
  3. using System.Text;  
  4. using System.Net;  
  5. using System.Net.Sockets;  
  6. using System.Threading;  
  7. using System;  
  8.   
  9.   
  10. namespace TCPServer  
  11. {  
  12.     public class ServerListen  
  13.     {  
  14.         public static void Run(Object iGetClientData)  
  15.         {  
  16.             IPEndPoint serverIP = new IPEndPoint(IPAddress.Parse("IP地址"), 端口);//本机预使用的IP和端口   
  17.             Socket skServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);  
  18.             skServer.Bind(serverIP);  
  19.             skServer.Listen(100);//连接客户端的上限   
  20.   
  21.             while (true)  
  22.             {  
  23.                 Socket skClient;  
  24.                 try  
  25.                 {  
  26.                     //当有可用的客户端连接尝试时执行,并返回一个新的socket,用于与客户端之间的通信   
  27.                     skClient = skServer.Accept();  
  28.                       
  29.                 }  
  30.                 catch (Exception ex)  
  31.                 {  
  32.                     LogHelper.Err("接收用户连接失败 ServerListen.Run Socket.Accept", ex);  
  33.                     continue;  
  34.                 }  
  35.   
  36.                 ThrClient thrC = new ThrClient(skServer, skClient, (IGetClientData)iGetClientData);  
  37.                 Thread t = new Thread(thrC.Run);  
  38.                 t.Start();  
  39.             }  
  40.         }  
  41.     }  
  42. }  
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类

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Net;  
  6. using System.Net.Sockets;  
  7. using System.Threading;  
  8.   
  9. namespace TCPServer  
  10. {  
  11.     public class ThrClient  
  12.     {  
  13.         private static readonly StringBuilder sb = new StringBuilder();  
  14.         private Socket skServer;  
  15.         private Socket skClient;  
  16.         private IPEndPoint clientIP;  
  17.         private IGetClientData iGetClientData;  
  18.   
  19.         //每次接收发送的临时信息   
  20.         private byte[] sendData;//发送的信息   
  21.         private byte[] receiveData = new byte[1024];//接收信息   
  22.         private int receiveN;  
  23.         private int netID;  
  24.         /// <summary>   
  25.         /// ThrClient构造方法   
  26.         /// </summary>   
  27.         /// <param name="pSkServer">服务端</param>   
  28.         /// <param name="pSkClient">客户端</param>   
  29.         public ThrClient(Socket pSkServer, Socket pSkClient,IGetClientData iGetClientData)  
  30.         {  
  31.             this.skServer = pSkServer;  
  32.             this.skClient = pSkClient;  
  33.             this.iGetClientData = iGetClientData;  
  34.   
  35.             this.clientIP = (IPEndPoint)this.skClient.RemoteEndPoint;  
  36.             //下面一定要使用UTF8而不能使用Uncode   
  37.             this.sendData = Encoding.UTF8.GetBytes("success");  
  38.             try  
  39.             {  
  40.                 this.skClient.Send(sendData, sendData.Length, SocketFlags.None);//发送信息   
  41.             }  
  42.             catch (Exception ex)  
  43.             {  
  44.                 LogHelper.Err("发送第一次连接成功信息 ThrClient.ThrClient Socket.Send", ex);  
  45.             }  
  46.         }  
  47.   
  48.         public void Run()  
  49.         {  
  50.             while (true)  
  51.             {  
  52.                 try  
  53.                 {  
  54.                     this.receiveN = skClient.Receive(this.receiveData);//接收   
  55.                     if (this.receiveN != 0)  
  56.                     {  
  57.                         string removeMsg = Encoding.UTF8 .GetString(receiveData, 0, receiveN);  
  58.                         iGetClientData.getThread(removeMsg);  
  59.                      }  
  60.                 }  
  61.                 catch (Exception ex)  
  62.                 {  
  63.                     iGetClientData.getClientIP(((IPEndPoint)skClient.RemoteEndPoint).Address);                     
  64.                     break;  
  65.                 }                  
  66.             }  
  67.         }  
  68.     }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值