2013-07-10 2 views
0

У меня есть клиент, который использует сокеты tcp для отправки и получения сообщений. Они дали нам IP-адрес назначения и порт. Чтобы понять это, я начал с небольшого консольного приложения, как клиента, сервера. Я использовал свой IP и порт. Начал работу с сервером. Затем отправил некоторую строку через клиент. Я смог увидеть его на консоли сервера. Эта программа устанавливает только одностороннее соединение client-> server. Как сделать два пути? Нужно ли мне использовать tcp-прослушиватель?Розетки и прослушиватели

Server: 
static void Main(string[] args) 
     { 
      sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
      IPEndPoint localEndpoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1234); 
      sck.Bind(localEndpoint); 
      sck.Listen(100); 

      Socket accepted = sck.Accept(); 
      Buffer = new byte[accepted.SendBufferSize]; 
      int bytesRead = accepted.Receive(Buffer); 
      byte[] formatted = new byte[bytesRead]; 
      for (int i = 0; i < bytesRead; i++) 
      { 
       formatted[i] = Buffer[i]; 
      } 
      string strData = Encoding.ASCII.GetString(formatted); 
      Console.WriteLine(strData); 
      Console.Read(); 
      sck.Close(); 
      accepted.Close(); 



     } 
Client: 
static void Main(string[] args) 
     { 
      sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
      IPEndPoint localEndpoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1234); 
     // IPEndPoint localEndpoint = new IPEndPoint(IPAddress.Parse("68.109.249.167"), 35520); 
      try 
      { 
       sck.Connect(localEndpoint); 

      } 
      catch(Exception ex) 
      { 
       Console.Write("unable to connect to remote endpoint"); 
       Main(args); 
      } 
      Console.Write("Enter Text"); 
       string text=Console.ReadLine(); 
      byte[] data= Encoding.ASCII.GetBytes(text); 

      sck.Send(data); 
      Console.Write("Data Sent!\r\n"); 
      Console.Write("Presee any key to continue"); 
      Console.Read(); 
      sck.Close(); 
     } 

Так что теперь этот демонстрационный клиент, сервер способен хорошо общаться.

В действительности, где играет слушатель? Мы устанавливаем соединение и отправляем запрос. sck.Listen(100); помещает сокет в состояние прослушивания. Будут ли они отправлять ответ на тот же порт. Нужно ли использовать класс Tcplistener? http://msdn.microsoft.com/en-us/library/bb397809%28v=vs.90%29.aspx. Пожалуйста, предложите

Спасибо

ответ

0

я задал вопрос об этом несколько лет назад.

Мой пример кода был очень полным, так что вы могли бы взглянуть на него:

TCP Client Connection

В принципе, ваш сервер будет слушать.

Клиент посылает сообщение на сервер, как это:

private int sendUsingTcp(string location) { 
    string result = string.Empty; 
    try { 
    using (var fs = new FileStream(location, FileMode.Open, FileAccess.Read)) { 
     using (var client = new TcpClient(GetHostIP, CpAppDatabase.ServerPortNumber)) { 
     byte[] riteBuf = new byte[client.SendBufferSize]; 
     byte[] readBuf = new byte[client.ReceiveBufferSize]; 
     using (var ns = client.GetStream()) { 
      if (ns.CanRead && ns.CanWrite) { 
      int len; 
      string AOK = string.Empty; 
      do { 
       len = fs.Read(riteBuf, 0, riteBuf.Length); 
       ns.Write(riteBuf, 0, len); 
       int nsRsvp = ns.Read(readBuf, 0, readBuf.Length); 
       AOK = Encoding.ASCII.GetString(readBuf, 0, nsRsvp); 
      } while ((len == riteBuf.Length) && (-1 < AOK.IndexOf("AOK"))); 
      result = AOK; 
      return 1; 
      } 
      return 0; 
     } 
     } 
    } 
    } catch (Exception err) { 
    MessageBox.Show(err.Message, "Message Failed", MessageBoxButtons.OK, MessageBoxIcon.Hand, 0); 
    return -1; 
    } 
} 

В принципе, сразу после того, я делаю запись: ns.Write(riteBuf, 0, len);

я прочитанный: ns.Read(readBuf, 0, readBuf.Length);

для там что-то для чтения, код на вашем сервере должен быть настроен для отправки ответа после получения данных.

Мой сервер был настроен так:

using (var ns = client.GetStream()) { 
    if (ns.CanRead && ns.CanWrite) { 
    int len; 
    byte[] AOK = Encoding.ASCII.GetBytes("AOK"); 
    using (var fs = new FileStream(location, FileMode.Create, FileAccess.Write)) { 
     do { 
     len = ns.Read(buf, 0, client.ReceiveBufferSize); 
     fs.Write(buf, 0, len); 
     ns.Write(AOK, 0, AOK.Length); 
     } while ((0 < len) && ns.DataAvailable); 
    } 
    byte[] okBuf = Encoding.ASCII.GetBytes("Message Received on Server"); 
    ns.Write(okBuf, 0, okBuf.Length); 
    } 
} 

Я надеюсь, что это ясно.

UPDATE:

Если вам нужно конкретное сообщение возвращается, что может быть сделано, но я не знаю, где вы должны добавить в данных.

private const string FMT_REPLY = 
    "POST_/OKMMISPOS_HTTP/5.1 " + 
    "Content-Length:_521 ISA*00*" + 
    "__________*00*" + 
    "__________*ZZ*500000330" + 
    "______*ZZ*731476619" + 
    "______*090303*1414*U*004"; 

Это, кстати, неприятное сообщение.

Используя константу, определенную выше, вы бы изменить код, чтобы быть:

byte[] AOK = Encoding.ASCII.GetBytes(FMT_REPLY); 
    using (var fs = new FileStream(location, FileMode.Create, FileAccess.Write)) { 
     do { 
     len = ns.Read(buf, 0, client.ReceiveBufferSize); 
     fs.Write(buf, 0, len); 
     ns.Write(AOK, 0, AOK.Length); 
     } while ((0 < len) && ns.DataAvailable); 
    } 
+0

Hi @ jp2code: Где вы точно отправляете сообщение на сервер и где выполняется прослушивание? Я скоро приступлюсь к нему, возможно, в ближайшие 2 часа .. :) – user575219

+0

Обновлен с клиентом, который читает ответ и сервер, который отправляет этот ответ. Вы можете, конечно, отредактировать эти ответы, чтобы быть тем, что хотите. Я выбрал короткий текст 'AOK'. – jp2code

+0

Как я могу добавить httpheader к исходящему сообщению. Могу я просто сделать простое приложение к фактическому сообщению. Они ожидают что-то вроде этого POST_/OKMMISPOS_HTTP/5,1 Content-Length: _521 ISA * 00 * __________ * 00 * __________ * ZZ * 500000330 ______ * ZZ * 731476619 ______ * 090303 * 1414 * U * 004 ... Я вторая часть на месте. Не знал, каким будет лучший способ отправить HTTP-заголовок. – user575219

0

Вы не должны использовать TCPListener класс на всех, вы могли бы просто использовать Socket.Listen для этой цели.Я подъехала код я написал полгода назад или около того (и до сих пор используется):

  _listenerThread = new Thread(() => 
      { 
       // Set up our server socket and set it to reuse addresses. 
       ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP); 
       ServerSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); 

       // Bind it to the local server. 
       ServerSocket.Bind(new IPEndPoint(IPAddress.Any, PortNumber)); 

       ServerSocket.Listen(MaxQueueLength); 

       // Once we get an incoming connection, let the HandleClientConnection handle it further. 
       ServerSocket.BeginAccept(HandleClientConnection, ServerSocket); 
      }); 

      _listenerThread.Start(); 

В данном конкретном случае, у меня есть отдельный поток для моего слушателя, и один раз в запросе входит в мой объект ServerSocket, вызывается HandleClientConnection, что в основном является рукопожатием между клиентом и сервером.

Чтобы убедиться в том, что мы продолжаем слушать новые связи после того, как мы приняли и зарегистрировали идущий, я добавил следующее к finally блоку HandleClientConnection:

  // Whatever happens, we want to make sure we start listening to incoming connections after handling the current one. 
      ServerSocket.BeginAccept(HandleClientConnection, result.AsyncState); 

Что это делает, по существу, создать круг; когда новый клиент подключается, сервер принимает его, создает для него новый объект ClientConnection и возвращается к BeginAccept для прослушивания новых клиентов.

Я применяю то же самое, когда речь заходит о обработке сообщений от клиентов. Там очень полезный фрагмент кода на code review, что и я, основанный на вышеуказанном коде.