java和C#之間SOCKET通信的問題


轉自:http://www.cdtarena.com/javapx/201307/9170.html

  java和C#之間SOCKET通信的問題

  一、服務器端(使用java編寫)

  /**

  * 監聽客戶端的請求

  *

  */

  private static void socketService()

  {

  ExecutorService exec = Executors.newCachedThreadPool();

  try

  {

  ServerSocket server=new ServerSocket(5678);

  int i = 1;

  while(true)

  {

  MyLogManager.InfoLog(log, null,"等待連接第"+i+"個用戶...");

  try

  {

  Socket client=server.accept();

  MyLogManager.InfoLog(log, null,"第"+i+"個用戶連接完成!");

  exec.execute(new PDAServerWithDB(client));

  }

  catch(Exception whileExp)

  {

  String msg = "多線程處理連接失敗!";

  MyLogManager.ErrorLog(log, whileExp, msg);

  }

  i++;

  }

  }

  catch(IOException ioe)

  {

  String msg = "連接失敗!";

  MyLogManager.ErrorLog(log, ioe, msg);

  exec.shutdown();

  }

  }

  具體對於Socket信息的接受和發送在PDAServerWithDB類中處理

  信息處理分為:接收數據和發送數據

  服務端接收數據一律采用ReadLine()方法,這就要求客戶端在發送請求時要有行結束符。

  服務器的接收發送數據的代碼

  a)構造輸入輸出流

  InputStream inPut = s.getInputStream();

  OutputStream outPut = s.getOutputStream();

  PrintWriter outWriter=new PrintWriter(outPut);

  BufferedReader inputReader =new BufferedReader(new InputStreamReader(inPut));

  b)接收客戶端請求的代碼

  String request = inputReader.readLine();

  request = request.trim();

  request = request.replaceAll("\n", "");

  c)向客戶端發送文本數據的代碼

  outWriter.println(strInfo);

  outWriter.flush();

  d)向客戶端發送文件的代碼

  // 發送文件長度

  File file = new File(filePath);

  byte[] outBytes = new byte[1024];

  int count = 0;

  FileInputStream fileInput = new FileInputStream(file);

  ByteArrayOutputStream ow = new ByteArrayOutputStream();

  while ((count = fileInput.read(outBytes)) > 0) {

  MyLogManager.DebugLog(log, null, String.valueOf(count));

  ow.write(outBytes, 0, count);

  }

  outPut.write(ow.toByteArray());

  //outWriter.print(ow);//這個在JAVA客戶端時可以正常響應,而在C#客戶端中無法響應。

  //outWriter.flush();

  二、客戶端(使用java和c#兩個版本)

  1).發送請求信息(字符串格式)

  對於JAVA來說:直接使用PrintWrite類的println()方法即可。

  而對於C#來說:需要使用socket.Send(System.Text.Encoding.ASCII.GetBytes(msg + "\r"));需要在請求信息msg后面加上一個行結束標志符。http://www.cdtarena.com/php/

  2).接收數據(文本或者文件)

  2-1).java客戶端接收數據

  a)java接收文本的代碼示例:

  ******代碼示例*****

  log.info("開始連接服務器");

  InetAddress address = InetAddress.getByName(AppConfig.IP);//193.100.100.143);

  SocketChannel sc = SocketChannel.open(new InetSocketAddress(address,AppConfig.PORT));

  log.info("服務器連接成功");

  //連接成功 初始化流

  InputStream inputStream = Channels.newInputStream(sc);

  InputStreamReader is = new InputStreamReader(inputStream,"GBK");

  in = new BufferedReader(is);

  log.info("接收服務器的數據");

  String responseLine="";

  while ((responseLine = in.readLine()) != null)

  {

  //用readLine接收數據是,會自動拋棄換行符,如果為了保持數據的格式,需要在這里加上一個換行標識符

  returnStr += responseLine+"\n";

  }

  log.info("接收服務器的數據完畢");

  **************

  b)java接收文件的示例代碼:

  *****代碼示例*****

  log.info("開始連接服務器");

  InetAddress address = InetAddress.getByName("193.100.100.159");//193.100.100.143);

  SocketChannel sc = SocketChannel.open(new InetSocketAddress(address,AppConfig.PORT));

  log.info("服務器連接成功,開始初始化流");

  //連接成功 初始化流

  OutputStream outputStream = Channels.newOutputStream(sc);

  InputStream inputStream = Channels.newInputStream(sc);

  InputStreamReader inputStreamReader = new InputStreamReader(inputStream);

  byte[] b = new byte[1024];

  ByteArrayOutputStream bArrStream = new ByteArrayOutputStream(fileLength);

  int readCount = 0;

  while ((readCount = inputStream.read(b)) != -1)

  {
  log.info(readCount);

  bArrStream.write(b, 0, readCount);

  }

  log.info("size:"+bArrStream.toByteArray().length);

  log.info("接收服務器的數據完畢");

  **************

  2-2.) c#客戶端接收數據的代碼

  a)接收文本數據

  *****代碼示例*****

  Socket socket = null;

  MemoryStream memStream = null;

  string returnMsg = string.Empty;

  //與服務器建立連接

  socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

  IPAddress add = IPAddress.Parse(appConfig.Ip);

  IPEndPoint endPt = new IPEndPoint(add, appConfig.Port);

  socket.Connect(endPt);

  //接收數據

  byte[] buffer = new byte[1024];

  int recCount = 0;

  memStream = new MemoryStream();

  //接收返回的字節流

  while ((recCount = socket.Receive(buffer)) > 0)

  {

  memStream.Write(buffer, 0, recCount);

  }

  Encoding encoding = Encoding.GetEncoding("GBK");

  returnMsg = encoding.GetString(memStream.GetBuffer(), 0, memStream.GetBuffer().Length);

  **************

  b)接收文件數據

  ****代碼示例****

  //接收數據

  byte[] buffer = new byte[1024];

  int recCount = 0;

  MemoryStream memStream = new MemoryStream();

  while ((recCount = socket.Receive(buffer)) > 0)

  {

  memStream.Write(buffer, 0, recCount);

  }

  //接下來按照文件格式,將memStream保存為文件即可

  **************

  =======以上是最終使用的代碼版本===========

  在開發過程中出現的問題及其解決

  1.)文本亂碼問題

  java服務器端代碼文件是使用GBK編碼。所以在客戶端讀取的時候使用GBK編碼進行轉換。

  2.)客戶端和服務端的交互。

  在服務端使用PrintWriter類來封裝數據發送流(發送數據),new BufferedReader(new InputStreamReader(InputStream))來封裝輸入流(讀取數據)

  服務端讀數據的時候是使用ReadLine方法,所以就要求客戶端發送請求時需要有一個行結束標志。對於java來說是用println()即可,

  而對於C#則需要在發送信息的后面手動增加一個行結束標識符"\r"。

  對於服務端的反饋信息有兩種反饋方式,一個是println(),一個是write(byte[])。前者是文本的發送,后者是文件的發送。

  在使用print(object)方法對文件發送時,java客戶端可是正確的接收數據,而C#客戶端卻不能,所以才采用了write(byte[])方法進行發送。

  接收數據時,還要對按行發送的文本數據進行去尾處理

  這個處理java和c#一樣,只是方法名的大小寫不同

  str = str.trim();

  str = str.replaceAll("\r", "");

  str = str.replaceAll("\n", "");


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM