我对C#中的.Net套接字有一点问题 . 我编写了一个客户端和一个使用TCP的服务器 .
当客户端打开时,它会向服务器发送握手 . 服务器用它的状态回答(clientexists,clientaccepted,...) . 之后,应用程序发送getdata-request,放弃连接并侦听服务器的“响应” . 现在,服务器构建与客户端的连接,并发送客户端所需的所有数据 .
代码和其他一切都有效,但问题是:
在我们公司的testserver上工作正常,在实时服务器上只有握手才能工作 . 在它之后,客户端不再接收任何数据 . 两个服务器上的服务应用程序是相同的 .
我认为问题是由一些防火墙引起的(服务器想要 Build 到客户端的tcp连接 - >不好),但是系统管理员说没有可以阻止它的防火墙 .
现在我正在寻找一种(“廉价”)解决方案,它不需要太多时间和代码更改 . 如果有人知道如何在理论上解决这个问题,那就太好了 .
顺便说一句:除了运行serverapplication之外,我不允许在实时服务器上做任何事情 . 我无法在此服务器上进行调试 .
我无法发布所有代码,但如果您需要查看其中的特定部分,请提出要求 .
- -编辑 - -
客户端 - 服务器通信
1)客户端启动
客户端发送握手(新的TCP连接)
2)服务器验证握手并保存IP
服务器响应它的客户端状态(相同的tcp连接)
3)客户确认此响应并放弃此连接
客户端发送getdata-request(新的tcp连接)
客户端也放弃了这个tcp连接
4)服务器接收getdata-request并在主数据库中收集所需的数据
服务器将所有收集的数据发送到客户端(多个tcp连接)
5)客户端接收所有数据并将其显示在其GUI中(多个tcp连接,并通过使用AutoResetEvents和Counts of socket发送来保存数据的顺序)
这是我的代码的主要部分 . 它's by far not the best but it was for me as I wrote it I guess. Step one, two and three work as intended. The processing of the data works fine, too. Another thing i forgot to mention is that the solution uses two Ports ' 16777 ' and ' 16778' . 一个接收/收听和一个发送 . 我的代码基于异步server和client的MSDN示例 .
发送握手(和getdata-request)
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-request | socToHandle应该是getdata-request先前连接的套接字)
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).Address);
(创建新连接)到使用相同连接的东西?如果这样可行,我该怎么做?并且客户端的侦听器部分是否仍然会收到单个数据包?
1 回答
服务器及其环境配置为正确处理传入请求 . 客户端通常位于路由器后面,默认情况下,它们无法接收来自网络外部的传入连接(这是一件好事) .
要启用传入连接,您可以将路由器配置为将特定端口号的所有请求转发到您的计算机 . 但是,您的网络上没有其他人能够运行客户端 .
这就是为什么在典型的多客户端 - 单服务器环境中,客户端进行所有连接,并且只有服务器需要对网络环境进行任何更改 .
我不知道你为什么选择从服务器端连接到客户端,但我强烈建议不要这样做 - 任何使用这种机制的廉价解决方案最终可能会变得非常昂贵 .