2009-04-01 6 views
0

좋아, 얘들 아 내 작은 두뇌를 깨고 해결책을 찾지 못했습니다. 여기에서의 문제는 begin-receive를 호출 할 수 있다는 것입니다. 그러나 그 후에는 메서드를 반복해서 호출 할 수있는 적절한 기술을 찾을 수 없습니다. 결과적으로 연결이 이루어지고 있지만 메시지는 한 번만 수신 할 수 있으며 그 이후에는 더 이상 수신 할 수 없습니다. 몹시 시급하기 때문에 도움을 요청하십시오. 나는 전체 코드를 여기에두고있다.소켓 프로그래밍

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Text; 
using System.Windows.Forms; 
using System.Net; 
using System.Net.Sockets; 
using System.Runtime.InteropServices; 
using System.IO; 
using.System.Threading; 

namespace WindowsApplication1 
{ 
public partial class lanmessenger : Form 
{ 

    Socket client; 
    Socket newSock, server, hostSock, remote; 


    byte[] receiveBuffer = new byte[1024]; 
    byte[] sendBuffer = new byte[1024]; 

    String dataEntered; 

    StringBuilder textbox1, receivedData, sb; 

    IPEndPoint serverIP, clientIP; 

    [DllImport("user32.dll")] 
    static extern bool HideCaret(IntPtr hWnd); 

    Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
    IPAddress localaddress = IPAddress.Parse("127.0.0.1"); 


    public void Receive() 
    { 
     if (remote.Connected) 
      remote.BeginReceive(receiveBuffer, 0, receiveBuffer.Length, System.Net.Sockets.SocketFlags.None, new AsyncCallback(OnReceivingData), remote); 
     else 
      return; 
    } 


    void OnReceivingData(IAsyncResult ar) 
    { 

     remote = (Socket)ar.AsyncState; 

     int recv = remote.EndReceive(ar); 

     receivedData = new StringBuilder(Encoding.ASCII.GetString(receiveBuffer, 0, recv)); 
     //MessageBox.Show(receivedData.ToString(), "received", MessageBoxButtons.OK); 

     sb = new StringBuilder(this.textBox1.Text); 
     sb.AppendLine(receivedData.ToString()); 

     if (textBox1.InvokeRequired) 
     { 
      this.Invoke((MethodInvoker)delegate { this.textBox1.Text = sb.ToString(); }); 

     } 
     //Receive();  


     return; 
    } 



    private void Accepted(IAsyncResult ar) 
    { 
     server = (Socket)ar.AsyncState; 
     client = server.EndAccept(ar); 
     /*if (client.Connected) 
      MessageBox.Show("client connected");*/ 

     try 
     { 
      client.BeginReceive(receiveBuffer, 0, receiveBuffer.Length, System.Net.Sockets.SocketFlags.None, new AsyncCallback(OnReceivingData), client); 
     } 
     catch (ArgumentException) 
     { 
      MessageBox.Show("arguments incorrect in begin-receive call", "Error", MessageBoxButtons.OK); 
     } 
     catch (SocketException) 
     { 
      MessageBox.Show("error in accessing socket while receiving", "Error", MessageBoxButtons.OK); 
     } 
     catch (ObjectDisposedException) 
     { 
      MessageBox.Show("socket closed while receiving", "Error", MessageBoxButtons.OK); 
     } 
     catch (Exception) 
     { 
      MessageBox.Show("error while receiving", "Error", MessageBoxButtons.OK); 
     } 

    } 

    public void FirstEndPoint() 
    { 
     newSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
     clientIP = new IPEndPoint(localaddress, 5555); 

     newSock.Bind(clientIP); 
     newSock.Listen(100); 

     try 
     { 
      newSock.BeginAccept(new AsyncCallback(Accepted), newSock); 
     } 
     catch (ArgumentException) 
     { 
      MessageBox.Show("Error in arguments while using begin-accept", "Error", MessageBoxButtons.OK); 
     } 
     catch (ObjectDisposedException) 
     { 
      MessageBox.Show("socket closed while using begin-accept", "Error", MessageBoxButtons.OK); 
     } 
     catch (SocketException) 
     { 
      MessageBox.Show("Error accessing socket while using begin-accept", "Error", MessageBoxButtons.OK); 
     } 
     catch (InvalidOperationException) 
     { 
      MessageBox.Show("Invalid operation while using begin-accept", "Error", MessageBoxButtons.OK); 
     } 
     catch (Exception) 
     { 
      MessageBox.Show("Exception occurred while using begin-accept", "Error", MessageBoxButtons.OK); 
     } 
    } 

    public void CreateThread() 
    { 
     Thread FirstThread = new Thread(new ThreadStart(FirstEndPoint)); 
     FirstThread.Start(); 
    } 

    public lanmessenger() 
    { 
     InitializeComponent(); 
     CreateThread(); 

    } 

    void OnSendingData(IAsyncResult ar) 
    { 
     Socket socket = (Socket)ar.AsyncState; 
     int AmtOfData = socket.EndSend(ar); 
     //MessageBox.Show(AmtOfData.ToString()); 

     return; 
    } 

    public void SendingData(Socket sock, String data) 
    { 
     textbox1.AppendLine(this.textBox2.Text); 

     if (textBox1.InvokeRequired) 
     { 
      this.Invoke((MethodInvoker)delegate { this.textBox1.Text = textbox1.ToString(); }); 
     } 


     if (textBox2.InvokeRequired) 
     { 
      this.Invoke((MethodInvoker)delegate { this.textBox2.Text = "\0"; }); 
     } 


     sendBuffer = Encoding.ASCII.GetBytes(data); 


     try 
     { 
      sock.BeginSend(sendBuffer, 0, sendBuffer.Length, SocketFlags.None, new AsyncCallback(OnSendingData), sock); 
     } 
     catch (ArgumentException) 
     { 
      MessageBox.Show("arguments incorrect in begin-send call", "Error", MessageBoxButtons.OK); 
     } 
     catch (SocketException ex) 
     { 
      String str1 = "error in accessing socket while sending" + ex.ErrorCode.ToString(); 
      MessageBox.Show(str1, "Error", MessageBoxButtons.OK); 
     } 
     catch (ObjectDisposedException) 
     { 
      MessageBox.Show("socket closed while sending", "Error", MessageBoxButtons.OK); 
     } 
     catch (Exception) 
     { 
      MessageBox.Show("error while sending", "Error", MessageBoxButtons.OK); 
     } 
    } 

    private void OnClientConnect(IAsyncResult ar) 
    { 
     Socket sock = (Socket)ar.AsyncState; 

     try 
     { 
      sock.EndConnect(ar); 
      if (sock.Connected) 
       MessageBox.Show("connected"); 

     } 
     catch (SocketException ex) 
     { 
      MessageBox.Show("Error in accessing socket while using end-connect" + ex.ErrorCode.ToString(), "Error", MessageBoxButtons.OK); 
      return; 

     } 

     if ((sock.Connected) && (dataEntered != "")) 
     { 
      SendingData(sock, dataEntered); 
     } 

    } 



    private void button1_Click(object sender, EventArgs e) 
    { 

     HideCaret(this.textBox1.Handle); 

     textbox1 = new StringBuilder(this.textBox1.Text); 
     dataEntered = this.textBox2.Text; 
     hostSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
     serverIP = new IPEndPoint(localaddress, 5555); 


     try 
     { 
      hostSock.BeginConnect(serverIP, new AsyncCallback(OnClientConnect), hostSock); 
     } 
     catch (ArgumentException) 
     { 
      MessageBox.Show("Error in arguments while using begin-connect", "Error", MessageBoxButtons.OK); 
      return; 
     } 
     catch (SocketException) 
     { 
      MessageBox.Show("Error in accessing socket while using begin-connect", "Error", MessageBoxButtons.OK); 
      return; 
     } 
     catch (ObjectDisposedException) 
     { 
      MessageBox.Show("socket closed while using begin-connect", "Error", MessageBoxButtons.OK); 
      return; 
     } 
     catch (InvalidOperationException) 
     { 
      MessageBox.Show("Invalid operation while using begin-connect", "Error", MessageBoxButtons.OK); 
      return; 
     } 

     catch (Exception) 
     { 
      MessageBox.Show("Exception while using begin-connect", "Error", MessageBoxButtons.OK); 
      return; 
     } 

    } 

} 

} 모든

답변

2

첫째, 당신은 좀 더 적절한 태그 귀하의 질문에 태그를 할 수 있습니다. 또한 비동기 TCP 클라이언트 메시징에 대한 MSDN 설명서에서 가져온 것이기 때문에 여기에서 설명서를 다시 참조 할 수 있습니다.

(현지 VS 도움말 URL에서 : MSDN Asynchronous Client Socket Example) 시작하는 새로운 비동기 작업이 콜백 방식에 실패 수신 이유

당신은 언급하지 않았다 - 당신은 어떤 오류를보고있다?

메시지를 성공적으로 수신하고 비동기 콜백에서 처리 한 경우 해당 메시지에서 수신을 다시 호출 할 수 있습니다 (사용자가 주석 처리했습니다). 상태 객체 (귀하의 경우에는 원격)를 재사용하는 경우 버퍼와 그 안에 유지되는 다른 객체를 모두 지워야합니다.

Receive 메서드에서 상태 개체를 초기화하고 새 비동기 수신 작업을 위해 다시 준비해야합니다.

또한 : 이전에 사용한 Receive Callback. 그것의 일부는 내가 (예를 들어, 이것은 파생 된 기본 클래스에서 메시지를 큐에 넣는 것과 같이) 작업하고 있던 앱에만 한정되어 있으며, 상당히 빠르고 빠르지 만 도움이 될 수 있습니다.

private void ReceiveCallback(IAsyncResult ar) 
    { 
     int bytesRead = 0; 

     try 
     { 
      // receive finished 
      if (ar.IsCompleted) 
      { 
       TcpIpState stateObject = (TcpIpState)ar.AsyncState; 
       bytesRead = stateObject.TcpIpSocket.EndReceive(ar, out seSocketError); 
       if (bytesRead > 0) 
       { 
        foreach (ArraySegment<byte> asBuffer in stateObject.Buffer) 
        { 

          stateObject.SBuilder.Append(
           Encoding.ASCII.GetChars(
           asBuffer.Array, 
           0, 
           asBuffer.Count)); 

        } 
        // Let the owner object know of the received message 
        base.EnqueueMessage(new TcpIpMessage(stateObject.SBuilder.ToString())); 

        // Start a new receive operation 
        stateObject.SBuilder = new StringBuilder(); 
        stateObject.Buffer.Clear(); 
        stateObject.Buffer.Add(new ArraySegment<byte>(new byte[_bufferSize])); 
        stateObject.TcpIpSocket.BeginReceive(
         stateObject.Buffer, 
         SocketFlags.None, 
         new AsyncCallback(ReceiveCallback), 
         stateObject); 
       } 
       else 
       { 
        OnDisconnected(this, new Exception("Bytes returned are 0")); 
        Disconnect(); 
       } 
      } 
     } 
     catch (Exception e) 
     { 
      // Something has gone wrong on a low level portion 
      OnDisconnected(this, e); 
      Disconnect(); 
     } 
    } 
+0

기타 : http://msdn.microsoft.com/en-us/library/bew39x2a.aspx – Acron

1

.NET에서 읽기 비동기 소켓 작업을 수행하는 표준 방법을 반복해서받을 콜백의 끝에서 BeginReceive를 호출하는 것입니다. Receive에 대한 전화가 필요한 것 같습니다. 그냥 전화를하지 말고 모두 제대로 작동해야합니다. 나는 당신의 코드에 대한 가장 상세한 검사를하지 않았기 때문에 뭔가를 놓친 것일 수있다. 그러나 이것은 시도한 첫 번째 것이다. 어쩌면 그 방법을 구현하면서 겪었던 정확한 문제를 자세히 설명해 주면 조금 더 도움이 될 것입니다.

명백하게 알 수 있듯이 .NET에서 TCP 통신을 수행하는 경우 (약간) 측면에서, TcpClient 클래스를 사용하는 것이 좋습니다. 이것은 하위 수준의 소켓 물건을 단순화하고 일반적으로 TCP 통신을 프로그래머에게 더 친숙하게 만듭니다! 비동기 독서 "루프"는 물론 동일합니다. 또한 다양한 목적을 위해 TcpClient 클래스를 적절하게 사용하는 방법에 대한 많은 다른 사이트 (예 : SO 포함)의 MSDN 및 자습서/코드 스 니펫에 대한 설명서가 많이 있습니다 (TcpClient 개체를 멀티 스레딩하거나 다시 사용하려고 할 때 조금 복잡해집니다) .

+0

TcpClient 클래스에 동의합니다. 삶을 훨씬 더 단순하게 만듭니다. Client 속성을 사용하여 저수준 소켓에 계속 액세스 할 수 있습니다. –