C#.Net套接字服务器客户端
我在C#中的.Net套接字中遇到了一些问题。 我编写了一个客户端和一个使用TCP的服务器。C#.Net套接字服务器客户端
当客户端打开时,它向服务器发送握手。服务器回答它的状态(客户端,客户端,...)。之后,应用程序发送getdata请求,放弃连接并监听服务器的“响应”。现在,服务器建立到客户端的连接并发送客户端需要的所有数据。
的代码和其他一切工作,但问题:
在我们公司TESTSERVER它工作正常,直播服务器只握手工作在。之后,客户端不会再收到任何数据。 Servepplication在两台服务器上都是一样的。
我认为这个问题是由一些防火墙引起的(服务器想建立到客户端的tcp连接 - >不好),但是系统管理员说没有防火墙可以阻止这个问题。
现在我正在寻找一种不需要太多时间和代码更改的('便宜')解决方案。如果有人知道如何从理论上解决这个问题,那就太好了。
BTW:除了运行服务器应用程序,我不允许在活服务器上执行任何操作。我无法在此服务器上进行调试。
我无法发布我的所有代码,但如果您需要查看它的特定部分,请索取。
---编辑---
客户端服务器通信
1)客户端启动
客户端发送握手(新的TCP连接)
2)服务器验证握手,并节省IP
服务器回应它的客户端状态(相同的TCP连接)
3)客户端确认此响应并放弃此连接
客户端发送getdata-request(新的tcp连接)
客户端放弃该TCP连接,过于
4)服务器接收的GetData请求并收集在主数据库
5)客户端接收所有需要的数据
服务器所有所收集的数据发送到客户端(多个TCP连接)数据并显示它在它的GUI
这是最主要的部分我的代码做(多个TCP连接和数据的顺序是由与插座的AutoResetEvents并计数派工作保持)。这是迄今为止不是最好的,但我认为这是我写的。第一步,第二步和第三步按预期工作。数据的处理也可以正常工作。 我忘记提及的另一件事是解决方案使用两个端口'16777'和'16778'。一个收/听,一个发送。 我的代码基于异步server和client的MSDN示例。
发送握手(和的GetData请求)
public void BeginSend(String data)
{
try
{
StateObject state = new StateObject();
state.workSocket = sender;
byte[] byteData = Encoding.UTF8.GetBytes(data);
sender.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback((IAsyncResult e) =>
{
Socket socket = (Socket)e.AsyncState;
SocketBase.StateObject stateObject = new SocketBase.StateObject();
stateObject.workSocket = socket;
socket.BeginReceive(stateObject.buffer, 0, 256, SocketFlags.None, new AsyncCallback(this.ReadCallback), (object)stateObject);
}), sender);
sender = RetrieveSocket(); //Socketreset
Thread.Sleep(100);
}
catch /*(Exception e)*/
{
//--
}
}
服务器监听
public void StartListening()
{
listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
try
{
listener.Bind(localEndPoint);
listener.Listen(System.Int32.MaxValue);
while (true)
{
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
}
catch (Exception e)
{
//--
}
}
public void AcceptCallback(...);
public void ReadCallback(...);
插槽发送
private void Send(Socket handler, String data)
{
Socket t = RetrieveSocket(((IPEndPoint)handler.RemoteEndPoint).Address);
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.UTF8.GetBytes(data);
// Begin sending the data to the remote device.
t.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), t);
}
套接字发送的所有数据部分(答案的GetData请求| socToHandle应该是getdata请求的上一个连接的套接字)
private void SendAllData(Socket socToHandle, string PakContent)
{
#region IsThereADatetime? //Resolve a given datetime
#region GiveClientNumberOfPackets //Send the client info about how much he has to receive (See line below)
Send(socToHandle, "ALERT#TASKCOUNT;OPT-" + GetBestDate(dateStart) + EndSocket);
#region #SendResouces
#region #SendGroups
#region #SendTasks
}
翻翻我的旧代码,我有一个想法=>
我能否通过改变发送一切通过相同的连接:
的Socket T = RetrieveSocket(((IPEndPoint)handler.RemoteEndPoint) 。地址);
(这将创建一个新的连接)的东西,使用相同的连接? 如果这可行,我该怎么做? 客户端的侦听器部分仍然会收到单个数据包吗?
服务器和他们的环境配置为正确处理传入的请求。客户端通常位于路由器后面,默认情况下,它们无法接收来自外部网络的传入连接(这是件好事)。
要启用传入的连接,则可以将路由器配置为某个端口号的所有请求转发到您的计算机。但是,您的网络上没有其他人能够运行客户端。
这就是为什么在典型的多个客户端 - 单个服务器环境中,客户端进行所有连接,并且只有服务器需要对网络环境进行任何更改。
我不知道你为什么选择从服务器端连接到客户端,但我会强烈反对这项建议 - 使用该机制可能变成是到底很贵任何廉价的解决方案。
感谢您的建议,我一定会在将来做到这一点,但我现在没有时间重写所有的代码。在任何客户端和服务器之间都没有路由器,只有第2层交换机。 – ShinuSha
假设系统管理员在于。 尝试使用https://technet.microsoft.com/en-us/sysinternals/jj729731.aspx端口上运行服务器和测试连接。上传试图ping您的客户端IP的代码版本。 也双方都应该经常测试防火墙/连接问题并记录它们。 – Nahum
您不必向我们展示“我的所有代码” - 事实上,这样做会适得其反。 *会有用的是你创建一个[MCVE](http://stackoverflow.com/help/mcve)。 –
TCP实现中的常见错误与处理接收到的流有关。接收过程必须考虑到可能在不同的块中接收到发送请求。需要使用长度值方法或使用分隔符来封装发送数据,例如, STX和ETX。 – Graffito