2021년 4월 30일 금요일

C# 멀티캐스트 소켓 생성

 protected Socket socket;   
 ...  

 void CreateMulticastSocket(string multicastIP, int port, bool exclusive)     
 {  
   sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);  
   
   socket.Blocking = false;  
   socket.ExclusiveAddressUse = exclusive;  
      
   if (!exclusive) socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);  
      
   IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, port);  
   socket.Bind(endpoint);  
    
   IPAddress ip = IPAddress.Parse(multicastIP);  
   socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(ip, IPAddress.Any));          
 }  

2021년 4월 8일 목요일

C# 시리얼 통신 데이터 파싱

시리얼 통신 데이터는 TCP와 유사하게 전송되는 바이트 길이만큼 수신되지 않는다. 

만약 송신자->수신자 에게 주기적으로 20 바이트를 전송한다고 했을때 수신측에서 시리얼 통신 데이터를 read 했을때 정확하게 20 바이트를 수신하지 않고 5+15 와 같이 잘려서 수신될 수 있다는 말이다. 
연속해서 데이터를 수신할때는 더욱 다양한 상황이 발생할 수 있다. 20, 20 바이트를 연속해서 보냈을때 25+15로 받을 수도 있고 1+15+15+9 와 같이 받을 수도 있다. 

이런 모든 경우의 수에 대해 올바르게 처리하려면 전송되는 데이터 단위가 고정길이(20 바이트)라고 가정했을때 수신 버퍼를 크게 할당한 다음 20 바이트씩 끊어서 처리해야 한다. 간단한 소스는 다음과 같다.

 
         private SerialPort serial = new SerialPort();  
         private byte[] serialRecvBuffer = new byte[1024];    // 수신버퍼  
         private int serialRecvBufferIndex = 0;    // 수신버퍼 인덱스 - 현재까지 수신한 데이터 길이와 같음  
         ...  
           
         serial.DataReceived += Serial_DataReceived;  
         ...  
           
         private void Serial_DataReceived(object sender, SerialDataReceivedEventArgs e)  
         {  
             try  
             {  
                 // 시리얼 데이터 수신  
                 int size = serial.BytesToRead;  
                 byte[] bytesRead = new byte[size];  
   
                 int ret = serial.Read(bytesRead, 0, size);  
   
                 // 수신버퍼에 복사  
                 Buffer.BlockCopy(bytesRead, 0, serialRecvBuffer, serialRecvBufferIndex, size);  
                 serialRecvBufferIndex += size;  
               
                 while (serialRecvBufferIndex >= 20)    // 수신버퍼 크기가 20보다 크거나 같으면 데이터 처리  
                 {  
                     ProcessSerialData();    // 데이터 처리  
   
                     // 데이터 처리 후 뒤에 남은 데이터들 앞으로 복사  
                     Buffer.BlockCopy(serialRecvBuffer, 20, serialRecvBuffer, 0, serialRecvBufferIndex - 20);  
                     serialRecvBufferIndex -= 20;  
                 }  
             }  
             catch (Exception ex)  
             {  
                 Console.WriteLine(ex.ToString());  
                 serialRecvBufferIndex = 0;  
             }  
         }