- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试使用 C# 开发服务器/客户端异步套接字。我遵循了 MSDN 上的指南关联。在我的例子中,套接字服务器监听特定端点,许多客户端可以一次连接到服务器,客户端可以与服务器通信,服务器可以与客户端通信。假设客户端 1 和客户端 2 与服务器连接,客户端 1 可以向服务器发送消息,服务器可以向客户端 1 发送消息,客户端 2 的情况相同。现在我希望客户端应该能够通过服务器相互通信。例如:client 2 想和client 1 通信,因为client 2 会向server 发送消息(这个消息会包含一些预设的字符;),然后server 会收到client 2 发来的文本,并得到client 1 的handler 并发送此消息发送给客户端 1,客户端 1 将响应服务器,现在我想将客户端 1 对该消息的响应发送给客户端 2,但我不知道该怎么做,因为客户端 1 通过其自己的处理程序与服务器进行通信,我在这里感到震惊,将不胜感激! 我的代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
namespace SocketServer
{
// 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 int clientNumber;
}
public class AsyncSocketServer
{
public static ManualResetEvent allDone = new ManualResetEvent(false);
public static Dictionary<int, StateObject> Clients = new Dictionary<int, StateObject>();
public static int connectedClient = 0;
public AsyncSocketServer()
{
}
public static void startListening() {
Byte[] bytes = new Byte[1024];
int Port = 1122;
IPAddress IP = IPAddress.Parse("127.0.0.1");
IPEndPoint EP = new IPEndPoint(IP, Port);
Socket listner = new Socket(IP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try
{
listner.Bind(EP);
listner.Listen(100);
while (true)
{
allDone.Reset();
Console.WriteLine("Waiting for the Connection......");
listner.BeginAccept(new AsyncCallback(AcceptCallBack), listner);
allDone.WaitOne();
}
}
catch(Exception e)
{
Console.WriteLine("Exception Occured ! in start listening method "+e.ToString());
}
Console.WriteLine("\nPress ENTER to continue...");
Console.Read();
}
public static void AcceptCallBack(IAsyncResult ar)
{
connectedClient++;
Console.WriteLine("client number " + connectedClient);
allDone.Set();
Socket listner = (Socket) ar.AsyncState;
Socket handler = listner.EndAccept(ar);
StateObject state = new StateObject();
state.clientNumber = connectedClient;
Clients.Add(connectedClient, state);
Console.WriteLine("total clients {0}",Clients.Count());
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.
try {
StateObject state = (StateObject) ar.AsyncState;
state.sb.Clear();
Socket handler = state.workSocket;
// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0) {
// 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.Substring(0, 3) == "cmd") {
foreach (StateObject Client in Clients.Values) {
if (Client.clientNumber == 1) {
Console.WriteLine("value is "+Client.clientNumber);
if (isClientConnected(Client.workSocket)){
Send(Client.workSocket, "did you receive my message");
//now client number 1 will response through its own handler, but i want to get response of
//client number 1 and return this response to client number 2
}
else {
string responsemsg = "client number " + Client.clientNumber + " is disconnected !";
Console.WriteLine(responsemsg);
Send(handler,responsemsg);
}
}
}
}
Console.WriteLine("Read {0} bytes from client {1} socket. \n Data : {2}",
content.Length, state.clientNumber,content);
// Echo the data back to the client.
if (isClientConnected(handler))
{
Send(handler, content);
}
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallBack), state);
}
}
catch (SocketException e)
{
//once if any client disconnected then control will come into this block
Console.WriteLine("Socket Exception Occured in Read Call Back : " + e.Message.ToString());
}
catch (Exception e)
{
//once if any client disconnected then control will come into this block
Console.WriteLine("Exception Occured in Read Call Back : " + e.Message.ToString());
}
}
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 bool isClientConnected(Socket handler){
return handler.Connected;
}
public static int Main(string[] args)
{
startListening();
return 0;
}
}
}
最佳答案
对于任何复杂的基于套接字的应用程序,我建议使用类似 DotNetty 的套接字库抽象传输层并让您专注于您的应用程序逻辑。查看他们的 SecureChat example ,它可能与您要实现的目标非常相似。
我整理了一个 DotNetty 服务器的简单示例,它允许您通过让客户端向服务器注册然后让服务器在客户端之间路由消息来在客户端之间发送命令。
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
using DotNetty.Transport.Channels;
using Newtonsoft.Json;
using System.IO;
namespace MultiClientSocketExample
{
public enum Command
{
Register = 1, // Register a new client
SendToClient = 2, // Send a message from one client to antoher
DoClientAction = 3 // Replace this with your client-to-client command
}
// Envelope for all messages handled by the server
public class Message
{
public string ClientId { get; set; }
public Command Command { get; set; }
public string Data { get; set; }
}
// Command for seding a message from one client to antoher.
// This would be serialized as JSON and stored in the 'Data' member of the Message object.
public class SendToClientCommand
{
public string DestinationClientId { get; set; } // The client to receive the message
public Command ClientCommand { get; set; } // The command for the destination client to execute
public string Data { get; set; } // The payload for the destination client
}
// An object for storing unhandled messages in a queue to be processed asynchronously
// This allows us to process messages and respond to the appropriate client,
// without having to do everything in the ChannelRead0 method and block the main thread
public class UnhandledMessage
{
private readonly Message message;
private readonly IChannelHandlerContext context;
public UnhandledMessage(Message message, IChannelHandlerContext context)
{
this.message = message;
this.context = context;
}
public Message Message => message;
public IChannelHandlerContext Context => context;
public Command Command => message.Command;
public string ClientId => message.ClientId;
public string Data => message.Data;
}
// A representation of the connected Clients on the server.
// Note: This is not the 'Client' class that would be used to communicate with the server.
public class Client
{
private readonly string clientId;
private readonly IChannelHandlerContext context;
public Client(string clientId, IChannelHandlerContext context)
{
this.clientId = clientId;
this.context = context;
}
public string ClientId => clientId;
public IChannelHandlerContext Context => context;
}
// The socket server, using DotNetty's SimpleChannelInboundHandler
// The ChannelRead0 method is called for each Message received
public class Server : SimpleChannelInboundHandler<Message>, IDisposable
{
private readonly ConcurrentDictionary<string, Client> clients;
private readonly ConcurrentQueue<UnhandledMessage> unhandledMessages;
private readonly CancellationTokenSource cancellation;
private readonly AutoResetEvent newMessage;
public Server(CancellationToken cancellation)
{
this.clients = new ConcurrentDictionary<string, Client>();
this.newMessage = new AutoResetEvent(false);
this.cancellation = CancellationTokenSource.CreateLinkedTokenSource(cancellation);
}
// The start method should be called when the server is bound to a port.
// Messages will be received, but will not be processed unless/until the Start method is called
public Task Start()
{
// Start a dedicated thread to process messages so that the ChannelRead operation does not block
return Task.Run(() =>
{
var serializer = JsonSerializer.CreateDefault(); // This will be used to deserialize the Data member of the messages
while (!cancellation.IsCancellationRequested)
{
UnhandledMessage message;
var messageEnqueued = newMessage.WaitOne(100); // Sleep until a new message arrives
while (unhandledMessages.TryDequeue(out message)) // Process each message in the queue, then sleep until new messages arrive
{
if (message != null)
{
// Note: This part could be sent to the thread pool if you want to process messages in parallel
switch (message.Command)
{
case Command.Register:
// Register a new client, or update an existing client with a new Context
var client = new Client(message.ClientId, message.Context);
clients.AddOrUpdate(message.ClientId, client, (_,__) => client);
break;
case Command.SendToClient:
Client destinationClient;
using (var reader = new JsonTextReader(new StringReader(message.Data)))
{
var sendToClientCommand = serializer.Deserialize<SendToClientCommand>(reader);
if (clients.TryGetValue(sendToClientCommand.DestinationClientId, out destinationClient))
{
var clientMessage = new Message { ClientId = message.ClientId, Command = sendToClientCommand.ClientCommand, Data = sendToClientCommand.Data };
destinationClient.Context.Channel.WriteAndFlushAsync(clientMessage);
}
}
break;
}
}
}
}
}, cancellation.Token);
}
// Receive each message from the clients and enqueue them to be procesed by the dedicated thread
protected override void ChannelRead0(IChannelHandlerContext context, Message message)
{
unhandledMessages.Enqueue(new UnhandledMessage(message, context));
newMessage.Set(); // Trigger an event so that the thread processing messages wakes up when a new message arrives
}
// Flush the channel once the Read operation has completed
public override void ChannelReadComplete(IChannelHandlerContext context)
{
context.Flush();
base.ChannelReadComplete(context);
}
// Automatically stop the message-processing thread when this object is disposed
public void Dispose()
{
cancellation.Cancel();
}
}
}
关于c# - C#中的异步套接字服务器,客户端通过套接字服务器进行客户端通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48365549/
我想在一些计算机之间建立点对点连接,这样用户就可以在没有外部服务器的情况下聊天和交换文件。我的第一个想法如下: 我在服务器上创建了一个中央 ServerSocket,所有应用程序都可以连接到该服务器。
我正在 Unity 中构建多人游戏。为此,我必须将一些值从客户端发送到两个或多个通过服务器连接的客户端。我想将其构建为服务器真实游戏。客户端将使用 Android,他们的数据将通过服务器同步(可能是一
练习 C 网络编程:我正在编写一个简单的 TCP 客户端-服务器应用程序,它应该将消息(在每个客户端的单独线程中)作为字符串从服务器发送到客户端并在客户端(稍后将成为控制台商店应用程序)。我首先发送消
我使用证书身份验证设置了 AWS Client VPN。我正在为客户端-客户端访问系统进行设置,基本上如 this AWS scenario/example 中所述.一切正常,如果我知道他们的 IP
我正在开发一个小型客户端1/客户端2、服务器(线程)TCP 游戏。在尝试处理延迟问题时,我意识到我的 transmitState() 中存在缺陷。它强制将不必要的信息传递到通讯流中,从而造成迟缓,将汽
来自文档:Configurable token lifetimes in Azure Active Directory (Public Preview) 它提到“ secret 客户端”,刷新 tok
Apollo 客户端开发工具无法连接到我的应用程序。我已在 ApolloClient 构造函数中将 connectToDevTools 传递为 true,但没有任何 react 。我也试过this p
我想在 Pod 内使用 Fabric8 kubernetes 客户端 (java)。如何获取部署集群的 kubernetes 客户端? 我可以使用该集群的 kubeconfig 文件获取任何集群的配置
我正在阅读 the security issue with Log4j我了解此产品受此漏洞影响。但是 Oracle 客户端 11.2 和 12 是否受此问题影响? 我找不到这些产品是否使用任何 Log
Eureka 服务器设置 pom.xml 1.8 Hoxton.SR1 org.springframework.cloud spring
我有一个点对点(客户端/服务器)设置(通过本地 LAN),它使用 Netty,一个 Java 网络框架。我使用原始 TCP/IP(例如,没有 HTTP)进行通信和传输。现在,根据要求,我们希望转向 T
上一篇已经实现了ModbusTcp服务器和8个主要的功能码,只是还没有实现错误处理功能。 但是在测试客户端时却发现了上一篇的一个错误,那就是写数据成功,服务器不需要响应。 接下来要做的就是实现Modb
有没有办法将二维十六进制代码数组转换为 png 图像? 数组看起来像这样(只是更大) [ [ '#FF0000', '#00FF00' ], [ '#0000FF'
我是套接字编程的新手。每次我运行客户端程序时,它都会说“无法连接到服务器”。谁能告诉我我在哪里犯了错误。任何帮助将不胜感激。 这是client.c #include #include #inclu
我们在UNIX环境下制作了简单的client.c和server.c程序。我们使用它来传输一个简单的文本文件,首先打开它,然后读取它并使用 open、read 和 send 系统调用发送;在客户端,我接
当我的程序来自 my previous question正在响应客户端,它应该发送加密消息。 当客户端连接时,它会发送一条类似“YourMessage”的消息。现在我想做的是,当客户端连接时,应该以某
我正在使用 C 和 putty 编写客户端/服务器程序。两个 c 文件位于同一系统上。 我目前在向客户端写回其正在使用的框架以及打印我的框架时遇到问题。它打印出 3 0 9 8,但随后开始打印 134
我正在使用 C 中的 select() 制作一个模拟快餐或其他任何东西的客户端服务器。 我有客户随机点 1-5 种“食物”。服务器每 30 秒决定一次。所有客户最喜欢的食物是什么?他为那些客户提供服务
对于单机游戏,基本的游戏循环是(来源:维基百科) while( user doesn't exit ) check for user input run AI move enemies
1、CentOS安装TortoiseSVN 复制代码 代码如下: yum install -y subversion 2、SVN客户端命令
我是一名优秀的程序员,十分优秀!