最近在用Socket 做局域网内客户端和服务器端通讯的程序(也可以用做客户端和客户端间的通讯)。先贴出收发的方法,其他的方法我会不断的更新。欢迎大家留言,互相交流。
       发送的报文头信息为Struct类型,发送数据类型可以是String 也可以是一个类。在发送Struct类型或发送类时,必须先将这个类序列化为流,接收时再将流反序列化为对象。接收的缓冲区大小设为1024,先接收报文头,再根据报文头中发送数据的长度来接收数据(当然,也可以开一个很大的缓冲区来接数据,但可能会比较浪费资源)。
1、发送的方法。
          在调用这个方法时,需要在实例化类时传入两个参数:目标IP和目标计算机的监听端口号。
public int CMSend(Object tcpHeader, Object objData, int outTime)
         {
             int flag = 0;
             try
             {
                 StartClient();
                 TcpHead structHead = (TcpHead)tcpHeader;
                 byte[] btyData = null;
                 byte[] btySendHead = new byte[32];
                 string strData = string.Empty;
                 switch (structHead.MessageType)
                 {
                     case "String":
                         strData = objData.ToString();
                         btyData = Encoding.ASCII.GetBytes(strData);
                         structHead.MessageLength = strData.Length;
                         break;
                     case "BaseDataContainer":
                         btyData = TransDataToByteArray(objData, BasePage.enumParamType.BaseDataContainer.ToString());
                         structHead.MessageLength = btyData.Length;
                         break;
                     default:
                         break;
                 }
                 btySendHead = TransDataToByteArray(structHead, BasePage.enumParamType.Struct.ToString());
                 byte[] bytSendData = new byte[btySendHead.Length + btyData.Length];
                 btySendHead.CopyTo(bytSendData, 0);
                 btyData.CopyTo(bytSendData, btySendHead.Length);
                 if (m_clientSocket == null || m_clientSocket.Connected == false)
                 {
                     throw new ArgumentException("參數socket 為null,或者未連接到遠程計算機");
                 }
                 if (bytSendData == null || bytSendData.Length == 0)
                 {
                     throw new ArgumentException("參數buffer 為null ,或者長度為 0");
                 }
                 int left = bytSendData.Length;
                 int sndLen = 0;
                 while (true)
                 {
                     if ((m_clientSocket.Poll(outTime * 1000000, SelectMode.SelectWrite) == true))// 收集了足够多的傳出數據后開始發送
                     {
                         sndLen = this.m_clientSocket.Send(bytSendData, sndLen, left, SocketFlags.None);
                         left -= sndLen;
                         if (left == 0)
                         {                                        // 數據已經全部發送
                             flag = 0;
                             break;
                         }
                         else
                         {
                             if (sndLen > 0)
                             {                                     // 數據已經部分被發送
                                 continue;
                             }
                             else
                             {                                     // 發送數據發生錯誤
                                 flag = -2;
                                 break;
                             }
                         }
                     }
                     else
                     {                                             // 超時退出
                         flag = -1;
                         break;
                     }
                 }
             }
             catch (System.NullReferenceException e)
             {
                 MessageBox.Show("連接失敗", "INF:001", MessageBoxButtons.OK, MessageBoxIcon.Information);
             }
             catch (Exception e)
             {
                 MessageBox.Show("發送失敗", "INF:001", MessageBoxButtons.OK, MessageBoxIcon.Information);
             }
            
             finally
             {
                 this.close();
             }
             return flag;
         }
2、接收方法
在调用这个方法时,需要在实例化类时传入一个参数:本地的监听端口号。
public Hashtable CMReceive()
         {
             if (firstFlag == true)
             {
                 tcpListener = new TcpListener(receivePort);
                 tcpListener.Start();
                 firstFlag = false;
             }
             while (true)
             {
                 listenSocket = tcpListener.AcceptSocket();
                 string strTcpHead = string.Empty;
                 byte[] bytTcpHead = new byte[1024];
                 byte[] receiveByte = new byte[1024];
                 byte[] bytReceiveData = null;
                 TcpHead structReceiveHead;
                 object objStructReceiveHead;
                 int bytes = 0;
                 int count = 0;
                 int messageLength;
                 int buffLength;
                 bool isHead = true;
                 while (true)
                 {
                     bytes = listenSocket.Receive(receiveByte, receiveByte.Length, SocketFlags.None);
                     bytTcpHead = receiveByte;
                     isHead = false;
                     break;
                 }
                 objStructReceiveHead = TransByteArrayToObject(bytTcpHead, BasePage.enumParamType.Struct.ToString());
                 structReceiveHead = (TcpHead)objStructReceiveHead;
                 messageLength = structReceiveHead.MessageLength;
                 if (messageLength % 1024 == 0)
                 {
                     buffLength = messageLength / 1024;
                 }
                 else
                 {
                     buffLength = messageLength / 1024 + 1;
                 }
                 if (count == 0)
                 {
                     bytReceiveData = new byte[buffLength * 1024];
                 }
                 while (true)
                 {
                     bytes = listenSocket.Receive(receiveByte, receiveByte.Length, SocketFlags.None);
                     if (bytes <= 0)
                         break;
                     receiveByte.CopyTo(bytReceiveData, count * 1024);
                     count++;
                 }
                 object objReceiveData   = TransByteArrayToObject(bytReceiveData, structReceiveHead.MessageType);
                 Hashtable htTcpHead = new Hashtable();
                 htTcpHead.Add("objStructReceiveHead", structReceiveHead);
                 htTcpHead.Add("objReceiveData", objReceiveData);
                 return htTcpHead;
             }
         }
3、把对象转化为字节流的方法
public byte[] TransDataToByteArray(Object objectParam, string sendDataType)
         {
             BinaryFormatter bf = new BinaryFormatter();
             MemoryStream memoryStream = new MemoryStream();
             byte[] buff = null;
             switch (sendDataType)
             {
                 case "String":
                     string tempStr = objectParam.ToString();
                     Char[] tempChar = tempStr.ToCharArray();
                     buff = System.Text.Encoding.UTF8.GetBytes(tempChar);
                     break;
                 case "BaseDataContainer":
                     bf.Serialize(memoryStream, objectParam);
                     buff = memoryStream.ToArray();
                     break;
                 case "Struct":
                     bf.Serialize(memoryStream, objectParam);
                     byte[] tempByte = memoryStream.ToArray();
                     buff = new Byte[1024];
                     tempByte.CopyTo(buff, 0);
                     for (int k = tempByte.Length; k < 1024; k++)
                     {
                         buff.SetValue(Byte.Parse("1"), k);
                     }
                     break;
                 default:
                     break;
             }
             return buff;   
         }
4、把字节流反转为对象的方法
public object TransByteArrayToObject(byte[] byteTemp, string paramType)
         {
             if (paramType.Equals("String"))
             {
                 string object_temp = System.Text.Encoding.UTF8.GetString(byteTemp);
                 return object_temp;
             }
             else if (paramType.Equals("BaseDataContainer"))
             {
                 MemoryStream memoryStream = new MemoryStream(byteTemp);
                 BinaryFormatter bf = new BinaryFormatter();
                 BaseDataContainer object_temp = (BaseDataContainer)bf.Deserialize(memoryStream);
                 return object_temp;
             }
             else if (paramType.Equals("Struct"))
             {
                 MemoryStream memoryStream = new MemoryStream(byteTemp);
                 BinaryFormatter bf = new BinaryFormatter();
                 TcpHead object_temp = (TcpHead)bf.Deserialize(memoryStream);
                 return object_temp;
             }
             else
             {
                 return "Exception";
             }
         }
5、获取本地IP
#region 取得本地IP
         public string GetHostIP()
         {
             string strHostname = Dns.GetHostName();
             IPHostEntry strIP = Dns.GetHostEntry(strHostname);
             string localIPStr = strIP.AddressList[0].ToString();
             IPAddress localIP = IPAddress.Parse(localIPStr);
             return localIPStr;
         }
         #endregion
6、连接目标计算机
public void StartClient()
         {
             //Connect to a remote device.   
             try
             {
                 IPHostEntry ipHostInfo = Dns.Resolve(this.m_strServerIP);
                 IPAddress ipAddress = ipHostInfo.AddressList[0];
                 IPEndPoint remoteEP = new IPEndPoint(ipAddress, this.m_nServerPort);
                 //Create a TCP/IP socket.   
                 this.m_clientSocket = new Socket(AddressFamily.InterNetwork,
                 SocketType.Stream, ProtocolType.Tcp);
                 //Connect to the remote endpoint.   
                 if (m_clientSocket.Connected)
                 {
                     close();
                 }
                 this.m_clientSocket.Connect(remoteEP);
             }
             catch (Exception e)
             {
                 this.ReportError("StartClient    found    a    error:\r\n" + e.ToString());
             }
         }