【问题标题】:Send packet from server to a specific client using TCP c#使用TCP c#将数据包从服务器发送到特定客户端
【发布时间】:2016-03-17 11:22:40
【问题描述】:

我目前正在编写一个客户端-服务器应用程序。客户端发送 UDP 广播消息尝试定位服务器,服务器发送 UDP 广播消息标识其位置。

当客户端收到标识服务器位置的消息时,它会尝试使用 socket.Connect(remoteEndPoint) 连接到服务器。

服务器在侦听套接字上侦听这些 TCP 请求,并使用 listensocket.accept() 接受请求。客户端详细信息存储在数组中(包括它们的 IP 和端口号)

客户端向服务器发送一条消息,其中包含有关用户输入的用户名和密码的信息。

服务器检查数据库中的用户名和密码,并根据结果向发送请求的客户端发送 TCP 消息(这是中断的地方),以使用侦听套接字检查 U&P。我正在尝试使用以下代码发送 TCP 消息,但由于出现错误,它无法正常工作。

TCPSocket.SendTo(message, clientsArray[i].theirSocket.RemoteEndPoint);

【问题讨论】:

  • 可以直接调用Socket.Connect(remoteEndPoint)捕获异常,查看服务器是否开启。通过这种方式,它会更简单。按照我说的做,您可以完全删除代码中 UDP 的存在。您可以通过clientsArray[i].theirSocket.Send(msg); 发送给连接的客户端。由于SendTo 仅用于 UDP。
  • 我只使用 UDP 来避免在服务器端使用如此多的资源,因为 UDP 无限期地广播服务器位置并不是一个好主意。我知道连接正常并且服务器已打开,因为我可以在客户端和服务器端看到它(消息出现在 GUI 上,说明客户端已连接),如果服务器关闭,客户端会出现一条消息。我正在尝试使用 TCPSocket.SendTo(message, clientsArray[i].theirSocket.RemoteEndPoint); 发送,这与您的完全相同,但我收到了错误。
  • 我说SendTo函数在UDP Only中使用,所以你应该只在Socket using TCP中使用Send函数我的答案。您可以完全忘记SendTo 函数,因为您使用的是 TCP。
  • 感谢邮件发送成功。抱歉,我没有在您的回复中发现 send 而不是 sendTo 。你真的很有帮助。

标签: c# tcp server client endpoint


【解决方案1】:

我不确定你使用的是什么方法。

但在 C# 中,有 2 个通用类可以用作服务器:TcpClient & Socket

TcpClient

...
//Start Server
Int32 port = 13000;
IPAddress localAddr = IPAddress.Parse("127.0.0.1");
server = new TcpListener(localAddr, port);
server.Start();

//Accept Client
TcpClient client = server.AcceptTcpClient();            

NetworkStream stream = client.GetStream();
String data = "Message From Server";
byte[] msg = System.Text.Encoding.ASCII.GetBytes(data);

//Send to Client
stream.Write(msg, 0, msg.Length);
...

使用 TCP 的套接字

...
//Start Server
Socket listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress hostIP = (Dns.Resolve(IPAddress.Any.ToString())).AddressList[0];
IPEndPoint ep = new IPEndPoint(hostIP, port);
listenSocket.Bind(ep); 
listenSocket.Listen(backlog);

//Accept Client
Socket handler = listener.Accept();

String data = "Message From Server";
byte[] msg = Encoding.ASCII.GetBytes(data);

//Send to Client
handler.Send(msg);
...

使用 UDP 的套接字

你不应该在你的服务器上使用它,因为你使用的是 TCP

...
IPHostEntry hostEntry = Dns.GetHostEntry(Dns.GetHostName());
IPEndPoint endPoint = new IPEndPoint(hostEntry.AddressList[0], 11000);

Socket s = new Socket(endPoint.Address.AddressFamily, SocketType.Dgram, ProtocolType.Udp);

String data = "Message From Server";
byte[] msg = Encoding.ASCII.GetBytes(data);
//Send to Client by UDP
s.SendTo(msg, endPoint);
...

【讨论】:

  • @JOsh 这只是一个简单的示例,用于教授如何使用这些类。真正的服务器看起来不是这样的。服务器将是多线程的,每个客户端都有一个或两个线程。
  • 所以你可以创建一个用于接受客户端的线程,在接受客户端之后,你应该为连接的客户端创建一个接收循环线程,并且可能将套接字存储在一个数组中。
  • 当你要发送给客户端时,你可以从数组中获取Socket,然后用SendTo发送。
  • 使用 TCP 意味着您无法避免存储多个客户端套接字,因为这是它的工作方式。
  • 这正是我的应用程序中发生的事情(线程除外 - 我只是使用计时器)并且我确实使用 .RemoteEndPoint 从数组中获取了套接字,但是我得到了异常“发送请求或接收数据被禁止,因为套接字未连接并且(当使用 sendto 调用在数据报套接字上发送时)没有提供地址”
【解决方案2】:

通常,当您从客户端获得连接时,您将获得TcpClient。该类有一个方法GetStream()。如果您想向该客户端发送一些数据,只需将所需的数据写入该流即可。

【讨论】:

  • 好吧,这似乎就是我想要的。我是否仍然使用 Listensocket 的 sendTo 属性在流上发送数据。我只问,因为我没有看到 TcpClient 的任何 sendStream 属性。
  • here 中说SendTo 是“向指定的远程主机发送无连接数据报”。
  • @JOsh:对于通信,您只需调用 GetStream(),然后在给定流上调用所需的读取和写入方法(同步或异步)。就是这样。
  • 我不确定您使用的是连接的套接字还是未连接的套接字。我猜你正在使用连接的套接字,所以你应该参考here。因为使用未连接的 scoket 称为 UDP,我认为您不需要这个。
  • 监听套接字未连接。
猜你喜欢
  • 1970-01-01
  • 2014-01-16
  • 2013-04-07
  • 2019-06-29
  • 2018-09-24
  • 2015-12-26
  • 1970-01-01
  • 1970-01-01
  • 2019-01-01
相关资源
最近更新 更多