程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> Delphi socket連接.net Socket

Delphi socket連接.net Socket

編輯:Delphi

[csharp]     這幾天一直研究Delphi連接.net的socket程序,終於有一些進展。 需求: 服務端截取前4個字節,轉換為數字,次數字為業務代碼。將決定調用哪個業務邏輯。 [html]   using System;   using System.Collections.Generic;   using System.Text;   using System.IO;   using System.Net.Sockets;   using System.Threading;   using PivasUpdate;   using log4net;   using System.Reflection;   using System.Net;      namespace PivasUpdate   {          public class ServiceProcess       {           private const int LENGTH=1024;              private const int GETVERSION = 1;           private const int DOWNLOADNEW = 2;           private const int DOWNLOADFILE = 3;              public static AutoResetEvent allDone = new AutoResetEvent(false);           private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);           private string cliendAddres;           private string INSTALLPATH = ConfigUtils.GetWindowsServiceInstallPath(ConfigUtils.SERVICENAME);              public void ProcessCallback(IAsyncResult ar)           {               Socket handler = null;               try               {                      StateObject state = (StateObject)ar.AsyncState;                   handler = state.workSocket;                   cliendAddres = IPAddress.Parse(((IPEndPoint)handler.RemoteEndPoint).Address.ToString()) + ":"                   + ((IPEndPoint)handler.RemoteEndPoint).Port.ToString() + ":";                      int bytesRead = handler.EndReceive(ar);                   log.Info(cliendAddres + "接受到數據包大小:" + bytesRead + "字節");                         int control = BitConverter.ToInt32(state.buffer, 0);                      string c = UTF8Encoding.UTF8.GetString(state.buffer, 4, bytesRead - 4);                      switch (control)                   {                       case GETVERSION:                           log.Info(cliendAddres + "獲取最新版本,請求版本號:" + c);                           GetVersionNo(c, handler);                           break;                       case DOWNLOADNEW:                           log.Info(cliendAddres + "下載更新配置文件:" + INSTALLPATH+"/"+c);                           DownLoadNew(c, handler);                           break;                       case DOWNLOADFILE:                           log.Info(cliendAddres + "下載文件," + INSTALLPATH+"/"+c);                           DownLoadFile(INSTALLPATH + "/" + c, handler);                           break;                       default:                           break;                   }                  }               catch (Exception e)               {                   log.Error(cliendAddres + "程序出錯," + e.Message);               }               finally               {                   if (handler != null)                   {                       handler.Shutdown(SocketShutdown.Both);                       handler.Close();                       handler = null;                       log.Info("與客戶端:" + cliendAddres + "斷開連接。");                   }               }                         }              public void DownLoadFile(string filePath,Socket handler)           {               if (!File.Exists(filePath))               {                   string fail = "文件不存在.";                   log.Info(cliendAddres+"訪問文件:"+filePath+"不存在。");                   byte[] failBytes = Encoding.UTF8.GetBytes(fail);                   handler.BeginSend(failBytes, 0, failBytes.Length, 0, new AsyncCallback(SendCallBack), handler);                   allDone.WaitOne();                   return;               }                  handler.BeginSendFile(filePath, new AsyncCallback(delegate(IAsyncResult ar)                   {                       handler.EndSendFile(ar);                       allDone.Set();                       log.Info(cliendAddres+"發送文件:"+filePath+"成功.");                   }                   ), handler);               allDone.WaitOne();                 }                 public void DownLoadNew(string versioncode,Socket handler)           {               string[] strs = versioncode.Split('.');               string result = "";               List<byte> resbyte = new List<byte>();                  if (strs.Length != 3)               {                   result = "版本號錯誤";                   log.Warn(cliendAddres+"版本號錯誤," + versioncode);                   resbyte.AddRange(Encoding.UTF8.GetBytes(result));                   handler.BeginSend(resbyte.ToArray(), 0, resbyte.Count, 0, new AsyncCallback(SendCallBack), handler);                   return;               }                  FileStream stream = File.OpenRead(INSTALLPATH+"/version/" + versioncode + "/update.xml");               List<byte> list = new List<byte>();               int count = 0;                  byte[] buf = new byte[1024];               while ((count=stream.Read(buf,0,buf.Length))>0) list.AddRange(buf);                  handler.BeginSendFile(INSTALLPATH+"/version/" + versioncode + "/update.xml", new AsyncCallback(delegate(IAsyncResult ar)                   {                       handler.EndSendFile(ar);                       log.Info(cliendAddres+"發送文件成功,文件名update.xml");                       allDone.Set();                   }                   ), handler);               allDone.WaitOne();           }              public void GetVersionNo(string content,Socket handler)           {               string[] strs = content.Split('.');               string result = "";               List<byte> resbyte = new List<byte>();                  if (strs.Length != 3)               {                   result = "版本號錯誤";                   log.Warn(cliendAddres+"版本號錯誤,"+content);                   resbyte.AddRange(Encoding.UTF8.GetBytes(result));                   handler.BeginSend(resbyte.ToArray(), 0, resbyte.Count, 0, new AsyncCallback(SendCallBack), handler);                   return;               }                  string[] dirs = Directory.GetDirectories(INSTALLPATH+"/version");               for (int i = 0; i < dirs.Length; i++)               {                   if (dirs[i].EndsWith("\\"+content))                   {                       if (i != dirs.Length - 1)                       {                           result = Directory.CreateDirectory(dirs[i + 1]).Name;                           break;                       }                       else                       {                           result = dirs[i];                       }                   }               }                  if (result == "")               {                   resbyte.AddRange(Encoding.UTF8.GetBytes("沒有找到此版本。"));                   log.Warn(cliendAddres+"沒有找到版本:"+content);               }               else               {                   resbyte.AddRange(Encoding.UTF8.GetBytes(result));                   log.Info(cliendAddres+"發送新版本號:"+result);               }               handler.BeginSend(resbyte.ToArray(), 0, resbyte.Count, 0, new AsyncCallback(SendCallBack), handler);               allDone.WaitOne();           }                 private void SendCallBack(IAsyncResult ar)           {               try               {                   // Retrieve the socket from the state object.                   Socket handler = (Socket)ar.AsyncState;                      // Complete sending the data to the remote device.                   int bytesSent = handler.EndSend(ar);                   log.Info(cliendAddres+"發送成功,發送字節數:"+bytesSent);                   allDone.Set();                  }               catch (Exception e)               {                   log.Error(cliendAddres+"發送失敗:"+e.Message,e);               }           }                    }   }     以上代碼為服務端邏輯。   delphi使用TclientSocket連接服務端程序。   其中有幾大問題。 TclientSocket.sendBuf可以發送任意字符字節等數據,但是我們這塊的想法是前4個字節為數字,後面為自定義的字符串,因此這就需要將字節進行處理。 首先將數字轉換為4個字節數組,然後將字符串轉換為utf8編碼的字節數組然後進行組合,發送。意想不到的是程序發送成功後,沒有任何返回的結果。 然後在服務端進行代碼的跟蹤,發現服務端接受的字節數組順序已亂,轉換的數字已經出錯。因此不會返回任何的結果。   後來經過多方面原因的查找,發現在delphi中字節數組使用的是動態數組 array of byte ,delphi動態數組在經過socket緩沖區時,會出現數據混亂的現象,那如何解決呢? 經多面證實發現,使用靜態數組 array [1..5] of byte 可以發送成功,服務端也可以解碼成功。   但是如果數據是動態的,長度也不確定,那麼這種方式也是不適用的。所以程序還是需要改進的,可以這麼做所有的指令還有數據都是字符串,服務端首先解碼,轉換為字符串,然後在解析字符串的指令。 經過研究sendBuf的方法發現第一個參數需要的是一個指針類型,而我傳遞的是一個數組,按道理來說兩個的效果都是一樣的,都是數組的第一個元素的地址,但是情況明顯不是這樣的。直接將數組當作參數返回的數數組對象的地址,而將第一個數組元素作為參數傳遞,則會將第一個元素的地址傳遞。因此將參數換掉就ok。   下面看一下delphi使用靜態數組如何發送指令 [delphi]   var    arr2 : TBytes;    arr1 : array [0..14] of byte;    seendText : UTF8String;    rectext : WideString;   begin     mmo.Lines.Add('發送指令'+inttostr(1));     with client do     begin       Open;       //SetLength(arr1,4);       arr1[0]:=1;       seendText:= UTF8Encode('1.1302.1714');       //SetLength(arr1,Length(arr1)+Length(seendText));       Move(seendText[1],arr1[4],Length(seendText));       client.Socket.SendBuf(arr1,Length(arr1));       rectext:=UTF8Decode(client.Socket.ReceiveText);       mmo.Lines.Add(rectext);       Close;     end;   end;    

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved