C++ rtmp livestream 流媒体

海阔天空 张翼飞翔

我的学习笔记。--我喜欢这里,因为这里安静,无广告骚扰。
随笔 - 82, 文章 - 2, 评论 - 126, 引用 - 0
数据加载中……

ZeroC ICE C#客户端 C++服务端 参数中包含有中文的string出错的解决方法


现象:
使用ICE做开发,C++的服务端,C#的客户端,如果返回的string参数中包含有中文,则C#客户端会抛异常。异常如下:

 

Ice.MarshalException
    reason 
=   " Invalid UTF8 string "
   在 IceInternal.ProxyFactory.checkRetryAfterException(LocalException ex, Reference 
ref , OutgoingAsync outAsync, Int32 &  cnt) 位置 d:\builds\distbuilds\release\Ice - 3.3 . 0 \cs\src\Ice\ProxyFactory.cs:行号  183
   在 Ice.ObjectPrxHelperBase.handleException__(ObjectDel_ 
delegate , LocalException ex, OutgoingAsync outAsync, Int32 &  cnt) 位置 d:\builds\distbuilds\release\Ice - 3.3 . 0 \cs\src\Ice\Proxy.cs:行号  880
   在 Ice.ObjectPrxHelperBase.handleExceptionWrapperRelaxed__(ObjectDel_ 
delegate , LocalExceptionWrapper ex, OutgoingAsync outAsync, Int32 &  cnt) 位置 d:\builds\distbuilds\release\Ice - 3.3 . 0 \cs\src\Ice\Proxy.cs:行号  919
   在 Demo.DemoIcePrxHelper.GetEx(String
&  strMsg, Dictionary` 2  context__, Boolean explicitContext__) 位置 E:\Workspace\VC ++ \Test\IceVC8\DemoIce\DemoC_cs\DemoC_cs\DemoIce.cs:行号  95
   在 Demo.DemoIcePrxHelper.GetEx(String
&  strMsg) 位置 E:\Workspace\VC ++ \Test\IceVC8\DemoIce\DemoC_cs\DemoC_cs\DemoIce.cs:行号  67
   在 IceClientCon.Program.Main(String[] args) 位置 E:\Workspace\VC
++ \Test\IceVC8\DemoIce\DemoC_cs\DemoC_cs\Program.cs:行号  24
Caused by: System.Text.DecoderFallbackException: 无法将位于索引 
1  处的字节 [BA] 由指定的代码页转换为 Unicode。
   在 System.Text.DecoderExceptionFallbackBuffer.Throw(Byte[] bytesUnknown, Int32 index)
   在 System.Text.DecoderExceptionFallbackBuffer.Fallback(Byte[] bytesUnknown, Int32 index)
   在 System.Text.DecoderFallbackBuffer.InternalFallback(Byte[] bytes, Byte
*  pBytes)
   在 System.Text.UTF8Encoding.FallbackInvalidByteSequence(Byte
*  pSrc, Int32 ch, DecoderFallbackBuffer fallback)
   在 System.Text.UTF8Encoding.GetCharCount(Byte
*  bytes, Int32 count, DecoderNLS baseDecoder)
   在 System.String.CreateStringFromEncoding(Byte
*  bytes, Int32 byteLength, Encoding encoding)
   在 System.Text.UTF8Encoding.GetString(Byte[] bytes, Int32 index, Int32 count)
   在 IceInternal.BasicStream.readString() 位置 d:\builds\distbuilds\release\Ice
- 3.3 . 0 \cs\src\Ice\BasicStream.cs:行号  1810


于是我做了四组实验,分别返回中文string类型的参数到客户端,结果如下:
C++服务端  C# 客户端 异常
C++服务端  C++客户端 正常
C# 服务端  C# 客户端 正常
C# 服务端  C++客户端 乱码

分析原因:
c++下的string使用的是ASCII码,而c#的string使用的是unicode编码,查看ICE文档,发现ICE传输的时候使用的是UTF-8,我把ASCLL的string当做utf-8格式的string发送给C#客户端,C#客户端解码这种格式的时候当然出问题了。

解决问题:
解决方法有二种:1、通过传输字节流来代替string.  2、将C++服务端的ASCLL的编码sting 转换成utf-8编码的string再传输,使客户端服务端编码格式统一。

解决方法1:
通过传输字节流来代替string. 
ICE 部分代码:

sequence < byte >   ByteSeq; 
idempotent 
void  Test( out  ByteSeq strOutValue);


 

c++服务端部分代码:

void  CUserRequestI::Test(ByteSeq &  byteSeq,  const  ::Ice::Current &  ice)

 
string  strValue  =   " AB汉字没关系。 " ;
 printf(
" Test.In=%s\n " ,strIn.c_str());
 
int  i = 0 ;
 
for  ( i = 0 ; i < strValue.length(); i ++ )
 
{
  byteSeq.push_back(strValue.c_str()[i] ); 
 }

 printf(
" Test push=%d\n " ,i);
}


 

C#客户端部分代码:

private   void  Test()
{
 
byte [] strValue;
 userRequestPrx.Test(
out  strValue); // 调用ICE接口
 Encoding CnEnconding  =  Encoding.GetEncoding( " GB18030 " );  // GB2312
  string  str  =  CnEnconding.GetString(strValue);   
 Console.WriteLine(
" getStr={0} " ,str); // 输出正常的string
}


 

解决方法2:
将C++服务端的ASCLL的编码格式sting转换成utf-8格式的string再发送


ICE文件 DemoIce.ice

//http://www.cnweblog.com/fly2700/
   #ifndef DEMO_ICE
#define DEMO_ICE
module Demo
{
    
interface DemoIce
    
{
        idempotent 
void SetEx(string strMsg);//
        ["cpp:const"] idempotent void GetEx(out string strMsg);
    }
;
}
//end module
#endif



C++服务端代码:
//File: DemoS.cpp


//http://www.cnweblog.com/fly2700/
  
#include 
< stdio.h >
#include 
< Ice / Ice.h >
#include 
< DemoIce.h >
#include 
< Windows.h >
using   namespace  Demo;
using   namespace  std;


void  unicodeToUTF8( const  wstring  & src,  string &  result)
{
 
int  n  =  WideCharToMultiByte( CP_UTF8,  0 , src.c_str(),  - 1 0 0 0 0  );
 result.resize(n);
 ::WideCharToMultiByte( CP_UTF8, 
0 , src.c_str(),  - 1 , ( char * )result.c_str(), result.length(),  0 0  );
}


void  unicodeToGB2312( const  wstring &  wstr ,  string &  result)
{
 
int  n  =  WideCharToMultiByte( CP_ACP,  0 , wstr.c_str(),  - 1 0 0 0 0  );
 result.resize(n);
 ::WideCharToMultiByte(CP_ACP, 
0 , wstr.c_str(),  - 1 , ( char * )result.c_str(), n,  0 0  );
}


void  utf8ToUnicode( const   string &  src, wstring &  result)
{
 
int  n  =  MultiByteToWideChar( CP_UTF8,  0 , src.c_str(),  - 1 , NULL,  0  );
 result.resize(n);
 ::MultiByteToWideChar( CP_UTF8, 
0 , src.c_str(),  - 1 , (LPWSTR)result.c_str(), result.length());
}


void  gb2312ToUnicode( const   string &  src, wstring &  result)
{
 
int  n  =  MultiByteToWideChar( CP_ACP,  0 , src.c_str(),  - 1 , NULL,  0  );
 result.resize(n);
 ::MultiByteToWideChar( CP_ACP, 
0 , src.c_str(),  - 1 , (LPWSTR)result.c_str(), result.length());
}



class  DemoIceI :  public  Demo::DemoIce
{
 
public  :
  
  
virtual   void  SetEx( const  ::std:: string &  param,  const  ::Ice::Current &  )
  
{
   
string  strData;
   wstring strUnicode;     
   utf8ToUnicode(param,strUnicode);
   unicodeToGB2312(strUnicode, strData);
   printf(
" SetEx().called,UTF-8 code=%s \t gb2312=%s\n " ,param.c_str(), strData.c_str());
   
  }


  
virtual   void  GetEx(::std:: string &  param,  const  ::Ice::Current &  )  const  
  
{
   
string  strGB2312  =   " AB汉字接受 " ;
   wstring wstrUnicode;
   
string  strUTF8;
   gb2312ToUnicode(strGB2312,wstrUnicode);
   unicodeToUTF8(wstrUnicode,param);
   printf(
" GetEx().called,UTF-8 code=%s \t gb2312=%s\n " ,param.c_str(), strGB2312.c_str());
  }

}
;


int  main()
{
 
//////////////////////////////////////////////////////////////////////// // 
  int  status  =   0 ;
 Ice::CommunicatorPtr ic;
 
try  
 
{
  ic 
=  Ice::initialize();
  Ice::ObjectAdapterPtr adapter 
=  ic -> createObjectAdapterWithEndpoints( " DemoIceEndpoint " " default -p 10000 " );
  Demo::DemoIcePtr demoIcePtr 
=   new  DemoIceI();
  adapter
-> add(demoIcePtr, ic -> stringToIdentity( " DemoIce " ));
  adapter
-> activate();
  printf(
" server.start ok \n " );
  ic
-> waitForShutdown();
 }
  catch  ( const  Ice::Exception  &  ex)  {
  cerr 
<<  ex  <<  endl;
  status 
=   1 ;
 }
  catch  ( const   char   *  msg)  {
  cerr 
<<  msg  <<  endl;
  status 
=   1 ;
 }


 
if  (ic)
 
{
  ic
-> destroy();
 }

 
 
return  status;
}



 

C#客户端代码:
//File Program.cs




using  System;
using  System.Collections.Generic;
using  System.Text;
using  Demo;
namespace  IceClientCon
{
    
class  Program
    
{
        
public   static   void  Main( string [] args)
        
{
            
int  status  =   0 ;
            Ice.Communicator ic 
=   null ;
            
try
            
{
                ic 
=  Ice.Util.initialize( ref  args);
                Ice.ObjectPrx obj 
=  ic.stringToProxy( " DemoIce:tcp -h 127.0.0.1 -p 10000 " ).ice_twoway().ice_timeout( 200 ).ice_secure( false );
                DemoIcePrx demoIce 
=  DemoIcePrxHelper.checkedCast(obj);
                
if  (demoIce  ==   null )
                    
throw   new  ApplicationException( " Invalid proxy " );
                
string  strSetValue  =   " AB汉字发送 " ;
                
string  strGetValue  =   "" ;
                demoIce.SetEx(strSetValue);              
                demoIce.GetEx(
out  strGetValue);
                Console.WriteLine(
" Set={0},Get={1} " , strSetValue, strGetValue);
            }

            
catch  (Exception e)
            
{
                
string  strErr  =  e.ToString();
                Console.Error.WriteLine(e);
                status 
=   1 ;
            }

            Console.ReadLine();
            
if  (ic  !=   null )
            
{
                
try
                
{
                    ic.destroy();
                }

                
catch  (Exception e)
                
{
                    Console.Error.WriteLine(e);
                    status 
=   1 ;
                }

            }

            
if  (status  !=   0 )
            
{
                System.Environment.Exit(status);
            }

        }

    }

}



 

posted on 2010-05-10 19:02 ZhangEF 阅读(3021) 评论(3)  编辑  收藏 所属分类: Socket

评论

# re: ZeroC ICE C#客户端 C++服务端 参数中包含有中文的string出错的解决方法  回复  更多评论   

我也开始接触这个东西,.还是感觉很不错!
2010-08-19 09:07 | 香柱元

# re: ZeroC ICE C#客户端 C++服务端 参数中包含有中文的string出错的解决方法  回复  更多评论   

您好,我现在用C#+asp.net做前端.页面采用utf-8或者gb2312的编码,调用ice的服务端是C++写的.然后汉字保存到Oracle
数据库中就是乱码.我想知道我在客户端C#中把字符串编码改了呢.还是默认传过去,到C++那边再处理好呢.谢谢.
2010-09-07 16:39 | 香柱元

# re: ZeroC ICE C#客户端 C++服务端 参数中包含有中文的string出错的解决方法[未登录]  回复  更多评论   

To 香柱元
你的情况刚好和我相反,我是C++传输string到C#,你是C#传输string到C++
我认为你在C++服务端转码比较好。
C++中先用我demo里面的方法utf8ToUnicode
然后掉用unicodeToGB2312就可以了
2010-09-11 22:16 | ZhangEF