2009-01-12 96 views
2

我正在构建一个客户端/服务器应用程序来定期备份某些文件。基本上,客户端将监视某些文件的更改,并将其上传到服务器。然后服务器将接收它们并将用递增后缀保存它们(即“filename_v1”,“filename_v2”等)。现在,我设法完成了大部分工作,但出现了一些问题,我找不到与之相关的任何内容。用C编写Socket编程#

在我开始之前,请注意:

  • 我尽我所能去寻找我自己的解决方案。
  • 我遵循(并完成)了几个套接字编程教程。
  • 我不知道任何有C#和/或套接字编程经验的人。

这里的逻辑:

  1. 服务器启动时,就开始听。 (BeginAccept)
  2. 当客户端连接时,会创建一个“worker”套接字。
  3. 工人套接字开始接收。 (BeginReceive)/客户端发送文件(SendFile)
  4. 当收到数据时,文件被保存。 (也检查为早期版本,但它是这里无关紧要。)
  5. 转到3.(我们需要从同一个客户端获得更多的文件。)

1-4步的工作就好了。

下面是问题:在第5步中,即使服务器没有收到任何消息,onDataReceive(回调方法)被调用,服务器发现自己处于无限循环状态。我试图关闭(或断开)工人插座,但没有机会在那里。我开始怀疑,也许我的算法有点草率。

无论如何,任何意见,建议或帮助,高度赞赏。

+0

你能在这里发布一些代码,所以我们可以看到可能发生什么? – GEOCHET 2009-01-12 17:29:26

回答

1

我已经在一个套接字库上做了一些工作,它在过去的一年中用于在.NET中传输医学图像。早期,我们很难检测套接字何时关闭,但最终达到稳定的解决方案。

我们的应用程序使用NetworkStream来读取/写入套接字。我们有一个类似于您的线程,它是在新连接到达时创建的,用于读取和写入网络数据。我们调用下面的方法来轮询数据何时到达或连接何时关闭。如果您不想轮询,可以调整该方法以使用更长的超时时间。当我们知道数据可用时,我们从NetworkStream对象读取数据。

下面的关键点是零字节在套接字上发送,这似乎在套接字关闭时检测到,如注释中所述。 OnNetworkError方法仅用于启动正在关闭的线程。

史蒂夫

 

protected override bool NetworkHasData() 
{ 
    if (_socket == null) 
     return false; 

    // Tells the state of the connection as of the last activity on the socket 
    if (!_socket.Connected) 
    { 
     OnNetworkError(null, true); 
     return false; 
    } 

    // This is the recommended way to determine if a socket is still active, make a 
    // zero byte send call, and see if an exception is thrown. See the Socket.Connected 
    // MSDN documentation. Only do the check when we know there's no data available 
    try 
    { 
     List readSockets = new List(); 
     readSockets.Add(_socket); 
     Socket.Select(readSockets, null, null, 100000); 
     if (readSockets.Count == 1) 
     { 
      if (_socket.Available > 0) 
       return true; 
      OnNetworkError(null, true); 
      return false; 
     } 

     _socket.Send(new byte[1], 0, 0); 
    } 
    catch (SocketException e) 
    { 
     // 10035 == WSAEWOULDBLOCK 
     if (!e.NativeErrorCode.Equals(10035)) 
      OnNetworkError(e, true); 
    } 

    return false; 
} 
 
1

我想你应该看一看WCF。为什么重新发明套接字编程,当你可以使用一个消息传递应用程序,可以很容易地通过电线传输字节数组?

WCF将处理您当前正在尝试执行的安全性,数据传输和所有管道工作。当然,要传输文件,您将被迫将消息大小设置为高于默认值......但我会认真考虑在重新编码轮子之前使用WCF制作原型。

我建议以下资源:

2

请问你的回调实现EndReceive?

你是否传递一个状态对象?如果是这样,请将其中一个属性作为传递给BeginReceive的缓冲区,然后在回调中检查状态缓冲区以查看是否收到任何数据。如果没有,请不要继续循环。

struct SocketStateObject 
{ 
    public byte[] Buffer; 
    public Socket Socket; 
} 



Socket mySocket = new Socket(...); 
SocketStateObject state; 
state.Buffer = new byte[1024]; 
state.Socket = mySocket; 

socket.BeginReceive(state.Buffer, 0, state.Buffer.Length, 0, callback, state); 

//don't remember the signature 
public void callback(IAsyncResult a) 
{ 
    if (((SocketStateObject)a.State).Buffer.Length = 0) 
    //don't call socket.beginreceive again. 
}