2013-08-19 215 views
2

我已经建立了服务器和客户端之间的连接,客户端发送数据到服务器并接收响应,但我想从服务器发送数据到客户端并接收客户端到服务器的响应,是吗可能吗?这里是我的代码: [客户]:TCP服务器到客户端

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Net.Sockets; 
using System.Net; 
using System.Text; 
using System.Threading.Tasks; 
using System.Threading; 

namespace Multi_Client 
{ 
    class Program 
    { 
     private static Socket _clientSocket = new Socket 
      (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 

     static void Main(string[] args) 
     { 
      Console.Title = "Client"; 
      ConnectToServer(); 
      RequestLoop(); 
      Exit(); 
     } 

     private static void ConnectToServer() 
     { 
      int attempts = 0; 

      while (!_clientSocket.Connected) 
      { 
       try 
       { 
        attempts++; 
        Console.WriteLine("Connection attempt " + attempts); 
        _clientSocket.Connect(IPAddress.Loopback, 100); 
       } 
       catch (SocketException) 
       { 
        Console.Clear(); 
       } 
      } 

      Console.Clear(); 
      Console.WriteLine("Connected"); 
      _clientSocket.Send(Encoding.ASCII.GetBytes("C1")); 
     } 

     private static void RequestLoop() 
     { 
      Console.WriteLine(@"<Type ""exit"" to properly disconnect client>"); 

      SendRequest(); 
      ReceiveResponse(); 

     } 

     /// <summary> 
     /// Close socket and exit app 
     /// </summary> 
     private static void Exit() 
     { 
      SendString("exit"); // Tell the server we re exiting 
      _clientSocket.Shutdown(SocketShutdown.Both); 
      _clientSocket.Close(); 
      Environment.Exit(0); 
     } 

     private static void SendRequest() 
     { 
      Console.Write("Send a request: "); 
      string request = Console.ReadLine(); 
      SendString(request); 

      if (request.ToLower() == "exit") 
      { 
       Exit(); 
       return; 
      } 
     } 

     private static void SendString(string text) 
     { 
      byte[] buffer = Encoding.ASCII.GetBytes(text); 
      _clientSocket.Send(buffer, 0, buffer.Length, SocketFlags.None); 
     } 

     private static void ReceiveResponse() 
     { 
      byte[] buffer = new byte[2048]; 
      int received = _clientSocket.Receive(buffer, SocketFlags.None); 

      if (received == 0) return; 

      byte[] data = new byte[received]; 
      Array.Copy(buffer, data, received); 
      string text = Encoding.ASCII.GetString(data); 
      Console.WriteLine(text); 
     } 
    } 
} 

[服务器]:

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

namespace Server 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 
     private static Socket _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
     private static List<Socket> _clientSockets = new List<Socket>(); 
     private static readonly int _BUFFER_SIZE = 2048; 
     private static byte[] _buffer = new byte[_BUFFER_SIZE]; 
     string text; 
     Socket current; 
     Socket test; 
     delegate void SetTextCallback(string text); 

     private void SetText(string text) 
     { 
      // InvokeRequired required compares the thread ID of the 
      // calling thread to the thread ID of the creating thread. 
      // If these threads are different, it returns true. 
      if (this.richTextBox1.InvokeRequired) 
      { 
       SetTextCallback d = new SetTextCallback(SetText); 
       this.Invoke(d, new object[] { text }); 
      } 
      else 
      { 
       this.richTextBox1.Text += text + "\n"; 
      } 
     } 
     private void SetupServer() 
     { 
      SetText("Setting up server..."); 
      _serverSocket.Bind(new IPEndPoint(IPAddress.Any, 100)); 
      _serverSocket.Listen(5); 
      _serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null); 
      SetText("Server Setup"); 
     } 

     /// <summary> 
     /// Close all connected client (we do not need to shutdown the server socket as its connections 
     /// are already closed with the clients) 
     /// </summary> 
     private static void CloseAllSockets() 
     { 
      foreach (Socket socket in _clientSockets) 
      { 
       socket.Shutdown(SocketShutdown.Both); 
       socket.Close(); 
      } 

      _serverSocket.Close(); 
     } 

     private void AcceptCallback(IAsyncResult AR) 
     { 
      Socket socket = null; 

      try 
      { 
       socket = _serverSocket.EndAccept(AR); 
      } 
      catch (ObjectDisposedException) // I cannot seem to avoid this (on exit when properly closing sockets) 
      { 
       return; 
      } 

      _clientSockets.Add(socket); 
      socket.BeginReceive(_buffer, 0, _BUFFER_SIZE, SocketFlags.None, new AsyncCallback(ReceiveCallback), socket); 
      SetText("Client connected, waiting for request..."); 
      test = (Socket)AR.AsyncState; 
      _serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null); 
     } 
     private void ReceiveCallback(IAsyncResult AR) 
     { 
      current = (Socket)AR.AsyncState; 
      int received = 0; 

      try 
      { 
       received = current.EndReceive(AR); 
      } 
      catch (SocketException) 
      { 
       SetText("Client forcefully disconnected"); 
       current.Close(); // Dont shutdown because the socket may be disposed and its disconnected anyway 
       _clientSockets.Remove(current); 
       return; 
      } 

      byte[] recBuf = new byte[received]; 
      Array.Copy(_buffer, recBuf, received); 
      text = Encoding.ASCII.GetString(recBuf); 
      SetText("Received Text: " + text); 
      if (text.ToLower() == "get tim") // Client requested time 
      { 
       SetText("Text is a get time request"); 
       byte[] data = Encoding.ASCII.GetBytes(DateTime.Now.ToLongTimeString()); 
       current.Send(data); 
       SetText("Time sent to client"); 
      } 
      else if (text.ToString() == "C1") // Client wants to exit gracefully 
      { 
       SetText("Received :: C1"); 
       byte[] data = Encoding.ASCII.GetBytes(DateTime.Now.ToLongTimeString()); 
       current.Send(data); 
      } 

      else 
      { 
       SetText("Server is sending invalid packet"); 
       SetText("Warning Sent"); 
      } 
      current.BeginReceive(_buffer, 0, _BUFFER_SIZE, SocketFlags.None, new AsyncCallback(ReceiveCallback), current); 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      SetupServer(); 
     } 
     private void Send_Received(string mess) 
     { 
      byte[] data = Encoding.ASCII.GetBytes(mess); 
      test.Send(data); 
     } 
     private void button2_Click(object sender, EventArgs e) 
     { 
      CloseAllSockets(); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      Send_Received(textBox1.Text); 
     } 


    } 
} 
+1

你需要解释你做了什么,以及为什么它不工作。您留下的代码转储的大小足够大,以至于没有人可能会潜入并尝试从您写的很少的东西中弄清楚什么。 –

+0

好吧,我被封锁了,我不知道如何在客户端向服务器发送任何数据之前将数据从服务器发送到客户端 – user2695010

回答

3

简短的回答:是的,这是可能的。

长:有。您当前的代码以这种方式实现:

  • 服务器初始化并准备接收连接。
  • 客户端尝试连接。
  • 服务器接受连接,添加到clientSockets集合。
  • 客户端发送“C1”。
  • 服务器接收内容,解释并发回答案。
  • 客户收到答案。

然后你进入一个循环,因为没有其他内容被发送。您实现了一个同步协议 - 客户端会话,服务器回应,客户端将其转存到控制台。

让我提出的快速实现,因此您可以测试服务器 - >客户端 - >服务器交换:

  • 实现您的服务器上的异步定时器。
  • 10秒钟后,如果没有传入消息从特定客户端到达,请发送“PING?”消息。
  • 解析客户端上的传入内容。如果消息等于“PING?”,则用“PONG!”回答。

这是一个非常简单的QoS协议 - 您将测试连接的健康状况。

让我们知道你是否设法实现它。 =)

+0

非常感谢您的回答!我要检查所有这些,并让你知道是否结果。 – user2695010

+0

不客气:异步通信学习起来可能有点棘手,但一旦掌握了它,对于SaaS(系统即服务)解决方案而言,记住它是一个很好的概念。 – OnoSendai

+0

实际上,如果没有客户端向服务器发送内容,Socket变量为空,所以当服务器发送数据时,它显示“对象引用未设置为对象的实例”,并且再次感谢你,很棒! – user2695010

0

其实,我知道问题出在哪里,当服务器送东西到客户端和客户端尚未发送的东西,客户端不显示的东西,直到他送到另一个东西:O型 例(我知道它很复杂): 服务器发送C1并在控制台C1中显示发送给客户端:客户端什么都不做(他应该在控制台C1O中显示) 客户端发送Pa(随机)并在控制台中显示CAO:服务器接收Pa 客户端发送Ka(随机)并显示在控制台(无效的请求,因为服务器已收到Pa,因此它发送无效的请求文本) 即使我知道它不是:S

0

我解决它通过编辑RequestLoop功能:

private static void RequestLoop() 
    { 
     ReceiveResponse(); 

    } 

它`所有:)