2017-01-26 12 views
3

Я пишу некоторый сервер сокета, клиентское приложение, и у меня есть серьезная проблема. Моя цель - создать асинхронное серверное приложение на C# и базовую клиентскую APP в python. Когда я следую простым примерам, обе программы работают. Но когда я пишу асинхронный сервер с сообщениями read и write, отправляемыми с клиентского APP, он не работает.TCP C# Сервер Python Клиент не может связаться

Вот пример кода сервера, который я использую.

using System; 
using System.Net; 
using System.Net.Sockets; 
using System.Text; 
using System.Threading; 

// State object for reading client data asynchronously 
public class StateObject 
{ 
// Client socket. 
public Socket workSocket = null; 
// Size of receive buffer. 
public const int BufferSize = 1024; 
// Receive buffer. 
public byte[] buffer = new byte[BufferSize]; 
// Received data string. 
public StringBuilder sb = new StringBuilder(); 
} 

public class AsynchronousSocketListener 
{ 
// Thread signal. 
public static ManualResetEvent allDone = new ManualResetEvent(false); 

public AsynchronousSocketListener() 
{ 
} 

public static void StartListening() 
{ 
    // Data buffer for incoming data. 
    byte[] bytes = new Byte[1024]; 

    // Establish the local endpoint for the socket. 
    // The DNS name of the computer 
    // running the listener is "host.contoso.com". 
    IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName()); 
    IPAddress ipAddress = ipHostInfo.AddressList[0]; 
    IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 3333); 
    IPEndPoint ipLocal = new IPEndPoint(IPAddress.Any, 3333); 
    // Create a TCP/IP socket. 
    Socket listener = new Socket(AddressFamily.InterNetwork, 
     SocketType.Stream, ProtocolType.Tcp); 

    // Bind the socket to the local endpoint and listen for incoming connections. 
    try 
    { 
     listener.Bind(ipLocal); 
     listener.Listen(100); 

     while (true) 
     { 
      // Set the event to nonsignaled state. 
      allDone.Reset(); 

      // Start an asynchronous socket to listen for connections. 
      Console.WriteLine("Waiting for a connection..."); 
      listener.BeginAccept(
       new AsyncCallback(AcceptCallback), 
       listener); 

      // Wait until a connection is made before continuing. 
      allDone.WaitOne(); 
     } 

    } 
    catch (Exception e) 
    { 
     Console.WriteLine(e.ToString()); 
    } 

    Console.WriteLine("\nPress ENTER to continue..."); 
    Console.Read(); 

} 

public static void AcceptCallback(IAsyncResult ar) 
{ 
    // Signal the main thread to continue. 
    allDone.Set(); 

    // Get the socket that handles the client request. 
    Socket listener = (Socket)ar.AsyncState; 
    Socket handler = listener.EndAccept(ar); 

    // Create the state object. 
    StateObject state = new StateObject(); 
    state.workSocket = handler; 
    handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); 
} 

public static void ReadCallback(IAsyncResult ar) 
{ 
    String content = String.Empty; 

    // Retrieve the state object and the handler socket 
    // from the asynchronous state object. 
    StateObject state = (StateObject)ar.AsyncState; 
    Socket handler = state.workSocket; 

    // Read data from the client socket. 
    int bytesRead = handler.EndReceive(ar); 
    Console.WriteLine("\n Enters(0)"); 
    if (bytesRead > 0) 
    { 
     Console.WriteLine("\n Enters(1)"); 
     // There might be more data, so store the data received so far. 
     state.sb.Append(Encoding.ASCII.GetString(
      state.buffer, 0, bytesRead)); 

     // Check for end-of-file tag. If it is not there, read 
     // more data. 
     content = state.sb.ToString(); 
     if (content.IndexOf("<EOF>") > -1) 
     { 
      // All the data has been read from the 
      // client. Display it on the console. 
      Console.WriteLine("Read {0} bytes from socket. \n Data : {1}", 
       content.Length, content); 
      // Echo the data back to the client. 
      Send(handler, content); 
     } 
     else 
     { 
      Console.WriteLine("\n Detect"); 
      // Not all data received. Get more. 
      handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, 
      new AsyncCallback(ReadCallback), state); 
     } 
    } 
    Console.WriteLine("\n Enters(1)"); 

} 

private static void Send(Socket handler, String data) 
{ 
    // Convert the string data to byte data using ASCII encoding. 
    byte[] byteData = Encoding.ASCII.GetBytes(data); 

    // Begin sending the data to the remote device. 
    handler.BeginSend(byteData, 0, byteData.Length, 0, 
     new AsyncCallback(SendCallback), handler); 
} 

private static void SendCallback(IAsyncResult ar) 
{ 
    try 
    { 
     // Retrieve the socket from the state object. 
     Socket handler = (Socket)ar.AsyncState; 

     // Complete sending the data to the remote device. 
     int bytesSent = handler.EndSend(ar); 
     Console.WriteLine("Sent {0} bytes to client.", bytesSent); 

     handler.Shutdown(SocketShutdown.Both); 
     handler.Close(); 

    } 
    catch (Exception e) 
    { 
     Console.WriteLine(e.ToString()); 
    } 
} 


public static int Main(String[] args) 
{ 
    StartListening(); 
    return 0; 
} 
} 

и здесь питон код для простого тестового клиента

import socket 

HOST, PORT = "127.0.0.1", 3333 
data = "data" 
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 

try: 
    sock.connect((HOST, PORT)) 
    sock.sendall(data) 
    print data 
finally: 
    sock.close() 

Как я вставил некоторые отладки коды на сервере ReadCallback, я вижу, что процедура называется, но это не делает процесс полученные данные как сообщение. Кажется, у него нет конечной точки.

Любые идеи или решения будут оценены.

ответ

0

Не эксперт по C#, но думаю, у вас есть проблема с Python программой.

try: 
    sock.connect((HOST, PORT)) 
    sock.sendall("data") 
    print data 
finally: 
    sock.close() 

Вы пытаетесь напечатать data, который не определен. Следовательно, будет выполнена часть except (если она существует). Затем программа завершается закрытием сокета.

+0

да я должен обновить код только после рассогласование , – androidgame2014

+0

Вы получаете некоторую ошибку, если вы положили 'except' в блок' try/finally'? – Fejs

1

Ваш ReadCallback игнорирует случай, когда bytesRead == 0, что означает, что клиент прекратил отправку данных. Если ваш код Python действительно отправляет "data" без "<EOF>", ваше соединение просто забудется сервером C#.


Что касается вашего кода C#, есть несколько вещей, которые вы могли бы улучшить:

  • Использование ManualResetEventSlim, это быстрее, он не использует операционную систему ручку (если вы на самом деле не использовать WaitHandle недвижимость)

  • Вы должны обрабатывать исключения из EndAccept в AcceptCallback и EndReceive в ReadCallback, и, возможно, улучшить исключение руку лин в SendCallback

  • Вы создаете строку из вашего StringBuilder в ReadCallback каждый раз, который идет полностью против цели использования StringBuilder; Вы должны проанализировать каждую строку, которую вы получаете от Encoding.ASCII.GetString искать для каждого символа, <, E, O, F и > последовательно

 

// Add to StateObject 
public const string EOF = "<EOF>"; 
public int eofOffset = -1; 
public int searchOffset = 0; 

// In ReadCallback 
string data = Encoding.ASCII.GetString(state.buffer, 0, bytesRead); 
state.sb.Append(data); 
int o = state.searchOffset + state.eofOffset + 1; 
while (o < state.sb.Length) 
{ 
    if (state.sb[o] != StateObject.EOF[state.eofOffset + 1]) 
    { 
     state.eofOffset = -1; 
     state.searchOffset++; 
     o = state.searchOffset; 
    } 
    else 
    { 
     state.eofOffset++; 
     if (state.eofOffset == StateObject.EOF.Length) 
     { 
      break; 
     } 
     o++; 
    } 
} 

// Replace this: 
//content = state.sb.ToString(); 
//if (content.IndexOf("<EOF>") > -1) 
// with this: 
if (state.eofOffset == StateObject.EOF.Length) 
{ 
    // Here is a good place to turn the StringBuilder into a string 
    // Perhaps truncate data to send back up to state.searchOffset 
    // ... 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^