- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我试图创建一个能够实现我希望的 TCP 服务,但遗憾的是我陷入了最后的障碍。
场景:一个服务器实例正在运行,10 个客户端都连接在一起,一个客户端将发送一个命令,并接收响应。这一切都很好。然而,最后一种情况不起作用
当客户端发出“UPDATE”命令时,服务器应向所有连接的客户端发回一条消息,告知他们需要执行某些操作。
示例通信:
1
Client A GetTime -----> Server
Client A <----- Time is... Server
2
Client A UPDATE ------> Server
Client A <------- Ack Server
Client A <------- DoUpdate Server
Client B <------- DoUpdate Server
Client C <------- DoUpdate Server
上面的 Comms 1 有效,主要是因为调用发送和调用 reeive,但对于 comms 2,我无法解决如何实现这一点,至少在不打开第二个不理想的通信端口的情况下无法做到这一点。
当前基于微软文章的尝试
服务器
class Program
{
public static int Main(String[] args)
{
AsynchronousSocketListener.StartListening();
return 0;
}
}
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 static void StartListening()
{
// Data buffer for incoming data.
//var 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, 3030);
// Create a TCP/IP socket.
var listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
try
{
listener.Bind(new IPEndPoint(IPAddress.Any, 3030));
//listener.Bind(localEndPoint);
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((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.
var listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// Create the state object.
var state = new StateObject {WorkSocket = handler};
handler.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0, ReadCallback, state);
}
public static void ReadCallback(IAsyncResult ar)
{
// Retrieve the state object and the handler socket
// from the asynchronous state object.
var state = (StateObject)ar.AsyncState;
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.
var content = state.Sb.ToString();
if (content.IndexOf("<EOF>", StringComparison.Ordinal) > -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
{
// Not all data received. Get more.
handler.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0, ReadCallback, state);
}
}
}
private static void Send(Socket handler, String data)
{
// Convert the string data to byte data using ASCII encoding.
var byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
handler.BeginSend(byteData, 0, byteData.Length, 0, SendCallback, handler);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
var 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;
}
* */
}
客户端代码
class Program
{
public static int Main(String[] args)
//static void Main(string[] args)
{
Console.Title = "Client ";
AsynchronousClient.StartClient();
Console.ReadLine();
return 0;
}
}
public class StateObject
{
// Client socket.
public Socket WorkSocket = null;
// Size of receive buffer.
public const int BufferSize = 256;
// Receive buffer.
public byte[] Buffer = new byte[BufferSize];
// Received data string.
public StringBuilder Sb = new StringBuilder();
}
public class AsynchronousClient
{
// The port number for the remote device.
private const int Port = 3030;
// ManualResetEvent instances signal completion.
private static readonly ManualResetEvent ConnectDone =
new ManualResetEvent(false);
private static readonly ManualResetEvent SendDone =
new ManualResetEvent(false);
private static readonly ManualResetEvent ReceiveDone =
new ManualResetEvent(false);
// The response from the remote device.
private static String _response = String.Empty;
public static void StartClient()
{
// Connect to a remote device.
try
{
// Establish the remote endpoint for the socket.
// The name of the
// remote device is "host.contoso.com".
//IPHostEntry ipHostInfo = Dns.Resolve("host.contoso.com");
//??IPHostEntry ipHostInfo = Dns.Resolve("localhost");
//??IPAddress ipAddress = ipHostInfo.AddressList[0];
//??IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
// Create a TCP/IP socket.
var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// Connect to the remote endpoint.
//client.BeginConnect(remoteEP,
//new AsyncCallback(ConnectCallback), client);
var remoteEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), Port);
client.BeginConnect(remoteEP, ConnectCallback, client);
ConnectDone.WaitOne();
// set receive to another thread so we can constantly receive, doesn't work as intended
//var thread = new Thread(() => ReadThread(client));
//thread.Start();
// Send test data to the remote device.
Send(client, "This is a test<EOF>");
SendDone.WaitOne();
//test remove
// Receive the response from the remote device.
Receive(client);
ReceiveDone.WaitOne();
// Write the response to the console.
Console.WriteLine("Response received : {0}", _response);
// Release the socket.
//client.Shutdown(SocketShutdown.Both);
//client.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
// doesn't work as expected
private static void ReadThread(object ar)
{
var client = (Socket)ar;
while (true)
{
Receive(client);
ReceiveDone.WaitOne();
// Write the response to the console.
Console.WriteLine("Response received : {0}", _response);
}
}
private static void ConnectCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
var client = (Socket)ar.AsyncState;
// Complete the connection.
client.EndConnect(ar);
Console.WriteLine("Socket connected to {0}", client.RemoteEndPoint);
// Signal that the connection has been made.
ConnectDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void Receive(Socket client)
{
try
{
// Create the state object.
var state = new StateObject {WorkSocket = client};
// Begin receiving the data from the remote device.
client.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0, ReceiveCallback, state);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void ReceiveCallback(IAsyncResult ar)
{
try
{
// Retrieve the state object and the client socket
// from the asynchronous state object.
var state = (StateObject)ar.AsyncState;
Socket client = state.WorkSocket;
// Read data from the remote device.
int bytesRead = client.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));
// Get the rest of the data.
client.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0, ReceiveCallback, state);
}
else
{
// All the data has arrived; put it in response.
if (state.Sb.Length > 1)
{
_response = state.Sb.ToString();
}
// Signal that all bytes have been received.
ReceiveDone.Set();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void Send(Socket client, String data)
{
// Convert the string data to byte data using ASCII encoding.
var byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
client.BeginSend(byteData, 0, byteData.Length, 0, SendCallback, client);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
var client = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
Console.WriteLine("Sent {0} bytes to server.", bytesSent);
// Signal that all bytes have been sent.
SendDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
/*
public static int Main(String[] args)
{
StartClient();
return 0;
}
*/
}
以前有效的系统
服务器:
class Program
{
private static byte[] buffer = new byte[1024];
public static Socket _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
public static List<Socket> clientSockets = new List<Socket>();
static void Main(string[] args)
{
Console.Title = "Server, " + clientSockets.Count + " clients are connected";
SetupServer();
Console.ReadLine();
}
public static void SetupServer()
{
Console.WriteLine("Setting up server...");
_serverSocket.Bind(new IPEndPoint(IPAddress.Any, 3030));
_serverSocket.Listen(10);
_serverSocket.BeginAccept(AcceptCallback, null);
Console.ReadLine();// stops cmd from closing
}
public static void AcceptCallback(IAsyncResult AR)
{
Socket socket = _serverSocket.EndAccept(AR);
if (!clientSockets.Contains(socket))
clientSockets.Add(socket);
IPEndPoint remoteIPEndPoint = socket.RemoteEndPoint as IPEndPoint;
Console.WriteLine(remoteIPEndPoint.Address);
Console.WriteLine("Client Connected");
Console.Title = "Server, " + clientSockets.Count + " clients are connected";
socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, RecieveCallBack, socket);
_serverSocket.BeginAccept(AcceptCallback, null);
}
private static void RecieveCallBack(IAsyncResult AR)
{
var socket = (Socket)AR.AsyncState;
int received = socket.EndReceive(AR);
var databuff = new byte[received];
Array.Copy(buffer, databuff, received);
string s = Encoding.ASCII.GetString(databuff);
Console.WriteLine("Text Received: " + s);
string response = string.Empty;
switch (s.ToLower())
{
case "get time":
response = DateTime.Now.ToLongTimeString();
break;
case "hello":
response = "olleh";
break;
case "update clients":
response = "";
SendData("Ack", socket);
doUpdateClients();
break;
default:
response = "Invavlid Request";
break;
}
SendData(response, socket);
}
private static void SendData(string Data, Socket socket)
{
byte[] data = Encoding.ASCII.GetBytes(Data);
socket.BeginSend(data, 0, data.Length, SocketFlags.None, sendCallback, socket);
socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, RecieveCallBack, socket);
}
private static void doUpdateClients()
{
// need to send an update message to all the clients
var upd = new Thread((UpdateClients));
upd.Start();
}
private static void UpdateClients()
{
Thread.Sleep(5000);
foreach (var sock in clientSockets)
{
SendData("UpdateClients", sock);
}
}
private static void sendCallback(IAsyncResult AR)
{
var socket = (Socket)AR.AsyncState;
socket.EndSend(AR);
}
//
}
}
客户:
class Program
{
private static byte[] buffer = new byte[1024];
public static Socket _clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
static void Main(string[] args)
{
Console.Title = "Client ";
LoopConnect();
//ReceiveLoopStart();
//_clientSocket.Listen(10);
SendLoop();
Console.ReadLine();
}
private static void LoopConnect()
{
while (!_clientSocket.Connected)
{
try
{
_clientSocket.Connect(IPAddress.Parse("127.0.0.1"), 3030);
}
catch (SocketException se)
{
}
}
Console.WriteLine("Connected");
}
private static void ReceiveLoopStart()
{
//_clientSocket.Bind(new IPEndPoint(IPAddress.Any, 3030));
//_clientSocket.Listen(10);
_clientSocket.BeginAccept(AcceptCallback, null);
Thread receiveThread = new Thread(ReceiveLoop);
receiveThread.Start();
}
private static void ReceiveLoop()
{
_clientSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, RecieveCallBack, _clientSocket);
_clientSocket.BeginAccept(AcceptCallback, null);
}
private static void RecieveCallBack(IAsyncResult AR)
{
int received = _clientSocket.EndReceive(AR);
var databuff = new byte[received];
Array.Copy(buffer, databuff, received);
string s = Encoding.ASCII.GetString(databuff);
Console.WriteLine("Text Received: " + s);
string response = string.Empty;
switch (s.ToLower())
{
case "get time":
response = DateTime.Now.ToLongTimeString();
break;
case "hello":
response = "olleh";
break;
default:
response = "Invavlid Request";
break;
}
}
public static void AcceptCallback(IAsyncResult AR)
{
Socket socket = _clientSocket.EndAccept(AR);
Console.WriteLine("Client Connected");
socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, RecieveCallBack, socket);
_clientSocket.BeginAccept(AcceptCallback, null);
}
private static void SendLoop()
{
while (true)
{
Console.Write("Enter Request: ");
string req = Console.ReadLine();
var buffer = Encoding.ASCII.GetBytes(req);
_clientSocket.Send(buffer);
var tempBuff = new byte[1024];
int rec = _clientSocket.Receive(tempBuff);
var data = new byte[rec];
Array.Copy(tempBuff, data, rec);
Console.WriteLine("Received: " + Encoding.ASCII.GetString(data));
}
}
}
}
最佳答案
我这里没有可用的 C# 示例,但您需要学习的是使用 select api。
您只需要一个线程即可执行此操作。您使用同一个线程来处理在任何时间点使用的所有套接字。
如果没有人连接,你只有监听套接字。然后你只使用 select api 来观察那个套接字上发生的事情。当没有指定超时时,选择是一个阻塞调用。如果数据可用,则意味着您可以调用 accept。如您所知,accept 的结果是另一个套接字。您现在在选择中使用 2 个套接字。 select 将再次阻塞,直到其中一个套接字有数据为止。也许又是监听套接字,所以你在调用 accept 后得到另一个套接字。您现在在选择中使用 3 个套接字。假设现在其中一个接受套接字有可用数据,您将通过正确使用 select api 看到这一点。然后,您可以使用这些套接字中的任何一个通过它发送内容,当然,不用于发送的监听套接字除外。
更多信息可以在这里找到: http://www.codeproject.com/Articles/20066/A-scalable-client-server-using-select-socket-funct
它使用了我所解释的内容并给出了更详尽的解释。
关于c# - 具有双向通信的 TCP 服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30558958/
谁能解释一下 Server.MapPath(".")、Server.MapPath("~")、Server.MapPath(@"之间的区别\") 和 Server.MapPath("/")? 最佳答案
我不知道,为什么我们要使用 Server.UrlEncode() & Server.UrlDecode()?!在 QueryString 中我们看到 URL 中的任何内容,那么为什么我们要对它们进行编
我已经通过 WHM 在我的一个域上安装了 ssl 证书。网站正在使用 https://xyz.com . 但是它不适用于 https://www.xyz.com .我已经检查了证书,它也适用于 www
我已经使用 WMI 检测操作系统上是否存在防病毒软件,itz 正常工作并通过使用命名空间向我显示防病毒信息,例如 win xp 和 window7 上的名称和实例 ID:\root\SecurityC
我们有 hive 0.10 版本,我们想知道是否应该使用 Hive Server 1 或 Hive Server2。另一个问题是连接到在端口 10000 上运行的 Hive 服务器,使用 3rd 方工
我想在 C++ 中使用 Windows Server API 设置一个 HTTPS 服务器,我使用了示例代码,它在 HTTP 上工作正常,但我就是不能让它在 HTTPS 上工作。 (我不想要客户端 S
我写了一个非常基本的类来发送电子邮件。我用 smtp 服务器对其进行了测试,它工作正常,但是当我尝试使用我公司的交换服务器时,它给出了这个异常: SMTP 服务器需要安全连接或客户端未通过身份验证。服
我的应用程序包含一个“网关”DataSnap REST 服务器,它是所有客户端的第一个访问点。根据客户端在请求中传递的用户名(基本身份验证),请求需要重定向到另一个 DataSnap 服务器。我的问题
我有一个 Tomcat 服务器和一个 Glassfish4 服务器。我的 Servlet 在 Tomcat 服务器上启动得很好,但在 Glassfish4 服务器上给我一个“HTTP Status 4
我在 vmware 上创建了一个 ubuntu 服务器。我用它作为文件服务器。如果我通过托管虚拟机的计算机进行连接,则可以访问它。我无法从同一网络上的其他计算机执行此操作。提前致谢! 最佳答案 首先确
如何重启 Rails 服务器?我从 开始 rails server -d 所以服务器是分离的 我知道的唯一方法就是去做ps 辅助 | grep rails 并 kill -9关于过程#但是像这样杀死进
我实际上正在尝试找到编写一个简单的 XMPP 服务器的最佳方法,或者找到一个占用空间非常小的服务器。我只关心XMPP的核心功能(状态、消息传递、群组消息传递)。目前还在学习 XMPP 协议(proto
我实际上正在尝试找到编写简单 XMPP 服务器的最佳方法,或者找到一个占用空间非常小的方法。我只关心 XMPP 的核心功能(统计、消息、组消息)。目前也在学习 XMPP 协议(protocol),所以
我们正在尝试从 Java JAX-RS 适配器访问 SOAP 1.1 Web 服务。 我们正在使用从 WSDL 生成的 SOAP 客户端。 但是当解码 SOAP 故障时,我们得到以下异常: ... C
目前,我和许多其他人正在多个平台(Windows、OS X 和可能的 Linux)上使用 Python HTTP 服务器。我们正在使用 Python HTTP 服务器来测试 JavaScript 游戏
我有一个连续运行的服务器程序(C#/.NET 2.0 on Linux with mono),我想从 PHP 脚本连接到它以在网站上显示状态信息。 目的是创建一个(某种)实时浏览器游戏(无 Flash
所以我有一个单页客户端应用程序。 正常流程: 应用程序 -> OAuth2 服务器 -> 应用程序 我们有自己的 OAuth2 服务器,因此人们可以登录应用程序并获取与用户实体关联的 access_t
我们刚刚将测试 Web 服务器从 Server 2008 升级到 Server 2012 R2。我们有一个部署我们网站的批处理脚本。当它将站点推送到服务器时,它现在失败了。奇怪的是,我可以使用相同的发
建议一些加载SpagoBI服务器的方法,我尝试了所有方法来解析spagobi服务器。在 Catalina 中,错误是 - * SEVERE: Unable to process Jar entry [
当我们点击应用程序服务器(apache tomcat)时,它会创建一个线程来处理我们的请求并与 tomcat 连接,建立连接,tomcat 创建另一个线程来处理请求并将其传递给连接,连接线程将其传递给
我是一名优秀的程序员,十分优秀!