private void EndReceive(IAsyncResult asyncResult) { try { // Receive all data. var bytesReceived = _clientSocket.EndReceive(asyncResult); var state = asyncResult.AsyncState as StateObject; state.DataStream.AddRange(state.Data.Take(bytesReceived)); Array.Clear(state.Data, 0, state.Data.Length); // reset data stream for the next receive var packetData = state.DataStream.ToArray(); var packetSize = BitConverter.ToInt32(packetData, 0); if (packetSize == packetData.Length) { // Initialize a packet object to store the received data. var receivedData = Packet.Deserialize(packetData) as ChatPacket; if (receivedData.ChatMessage != null) { Console.WriteLine(receivedData.ChatMessage); } state.DataStream.Clear(); } // If the packet size doesn't equal the packet length, we will keep receiving more data until it does. // Continue listening for broadcasts. _clientSocket.BeginReceiveFrom(state.Data, 0, state.Data.Length, SocketFlags.None, ref _serverEndPoint, EndReceive, state); } catch (ObjectDisposedException) { Logger.WriteLine("Object was disposed."); } catch (Exception ex) { Logger.WriteLine("ReceiveData error!"); Logger.WriteLine(ex.Message); } }
private void Receive() { try { int count = 1; //현재 파일의 인덱스 int nRead = 0; //총 전송 횟수 while (ConnectedToServer) { this.NetStream.Read(this.ReadBuffer, 0, this.ReadBuffer.Length); //읽어오고 Packet p = (Packet)Packet.Deserialize(this.ReadBuffer); //해독해서 switch (p.Type) //타입에 따라 나눈다 { case 0: //보통의 파일 전송일 때 { Fp = (FilePacket)p; //파일을 보내기 위한 클래스로 다운캐스팅 nRead = (int)Fp.FileSize / Fp.FileData.Length + 1; //파일을 받아야 하는 횟수 int fileIndex = 1; //파일 중복 시 앞에 번호를 붙여주기 위한 인덱스 string fileName = PathTextBox.Text + "\\" + Fp.FileName; if (count == 1) //파일의 첫부분을 받았다면 { while (File.Exists(fileName)) //파일이 있는지 확인하고 { fileName = PathTextBox.Text + "\\" + "(" + fileIndex.ToString() + ")" + Fp.FileName; fileIndex++; //앞에 번호를 붙여 파일 이름이 겹치지 않도록 해준다 } f = new FileStream(fileName, FileMode.Create, FileAccess.Write); //중복되지 않는 파일 이름을 얻은 후 파일스트림을 생성한다(생성으로) } f.Write(Fp.FileData, 0, Fp.FileData.Length); this.Invoke(new MethodInvoker(delegate() //컨트롤 건드리는 부분 { this.ProgressBar.Maximum = nRead; //최대전송횟수로 초기화 this.ProgressBar.Minimum = 0; //최소는 0 this.ProgressBar.Value = count; //count는 현재 몇번 받았는지 나타냄 count++; } )); if (count > nRead) //count==nRead일 때 파일을 모두 받음 //따라서 count++을 한 직후 count>nRead 라면 파일을 다 받았으므로 { count = 1; //count를 다시 1로 초기화하고 f.Dispose(); f.Close(); //파일의 인덱스는 파일이 닫지 않으면 유지되기 때문에 //파일의 전송을 모두 끝낸 시점에서 닫아준다. } break; } case 1: //리스트뷰에 파일을 띄우기 위한 Type일 때 { Fl = (FileList)p; //리스트 뷰에 파일을 띄우기 위한 클래스로 다운캐스팅 this.Invoke(new MethodInvoker(delegate() //컨트롤을 건드리는 부분 { ListViewItem item = new ListViewItem(new string[] { Fl.FileName, Fl.FileSize.ToString() }); listView.Items.Add(item); //아이템을 파일이름, 사이즈로 생성 후 Add })); break; } case 2: //파일을 달라는 request일 때-->클라이언트에서는 받을 일 없음 { break; } } } } /* * catch (SocketException) //처음에 서버 연결이 끊겼을 때 자동으로 Disconnect 버튼이 * { //Connect 버튼으로 바뀌도록 하기 위해 만든 코드였는데, * Cli = null; //서버와 연결이 끊길 때 발생하는 Exception이 * NetStream = null; //SocketException 아니라 밑의 IOException이라는 것을 알고 주석처리하였다. * if (f != null) * f.Close(); * ConnectedToServer = false; * * Invoke(new MethodInvoker(delegate () * { * ConnectBtn.Text = "Connect"; * ConnectBtn.ForeColor = Color.Black; * listView.Items.Clear(); * })); * * threader.Abort(); * }*/ catch (System.IO.IOException) //서버와의 연결이 끊겼을 경우 or IO 예외가 발생했을 경우 { Cli = null; NetStream = null; //넷스트림과 클라이언트를 널로만듬 if (f != null) { f.Close(); //파일스트림이 널이 아니라면 닫고 } ConnectedToServer = false; //서버와 연결상태를 거짓으로 설정 Invoke(new MethodInvoker(delegate() //컨트롤을 건드리는 부분 { ConnectBtn.Text = "Connect"; //버튼의 텍스트를 Connect로 ConnectBtn.ForeColor = Color.Black; //색깔을 검정색으로 listView.Items.Clear(); //리스트뷰를 비움 })); threader.Abort(); //리시브 쓰레드 종료 thrsender.Abort(); //보내는 쓰레드 종료 } catch {//쓰레드가 중단되었습니다. 같은 무시할 수 있는 오류를 깔끔히 처리하기 위해서 비워둠 } }
public void run() { this.connection = true; this.m_NetStream = this.client.GetStream(); int c = 0; while (connection == true) { try { if (send_Thread.IsAlive == true) { Thread.Yield(); } this.m_NetStream.Read(this.readBuffer, 0, 1024 * 5); Packet packet = (Packet)Packet.Deserialize(readBuffer); readBuffer.Initialize(); if (packet.type == 0) { listView1.Items.Add(new ListViewItem( new string[] { packet.filename, (packet.filesize).ToString() } )); } else if (packet.type == 1) { listView1.Enabled = false; c = 0; count = ((int)packet.filesize / (1024 * 4)) + 1; size = (int)packet.filesize; FileStream wr = File.OpenWrite(textBox_Path.Text + packet.filename); progressBar1.Value = 0; progressBar1.Step = 1; progressBar1.Minimum = 0; progressBar1.Maximum = count; wr.SetLength(packet.filesize); wr.Close(); progressBar1.Focus(); } else if (packet.type == 2) { listView1.Enabled = false; FileStream wr = File.OpenWrite(textBox_Path.Text + packet.filename); wr.Position = 1024 * 4 * c; if (c != (count - 1)) { for (int i = 0; i < packet.filedata.Length; i++) { wr.WriteByte(packet.filedata[i]); } } if (c == (count - 1)) { for (int i = 0; i < wr.Length % (1024 * 4); i++) { wr.WriteByte(packet.filedata[i]); } } wr.Flush(); wr.Close(); c++; packet.filedata.Initialize(); progressBar1.PerformStep(); if (c == count) { listView1.Enabled = true; } } else if (packet.type == 999) { listView1.Items.Clear(); btn_connect.ForeColor = Color.Black; btn_connect.Text = "Connect"; m_NetStream.Close(); connection = false; m_thread.Abort(); } } catch (Exception ex) { MessageBox.Show("Connection fail"); connection = false; btn_connect.ForeColor = Color.Black; this.Invoke(new MethodInvoker(delegate() { this.btn_connect.Text = "Connect"; })); } } }