发送消息给网(类似于net send)

时间:2009-08-28 09:12:50

标签: c# .net sockets

我不确定这个话题是否已被讨论,但我不知道该怎么做。在c#中,我需要向我网络中的其他人发送消息。我做了一些研究,都指向套接字方法。使用这种方法,逻辑上它将如下工作:

  1. 打开套接字
  2. 对邮件进行编码(例如ascii)
  3. 将编码的字节放入数组
  4. 发送阵列
  5. 另一方面也有一个套接字打开,然后按相反的顺序进行相同的操作。
  6. 所以我找到了这段代码,任何人都可以帮我理解代码,这与我想要的类似:

    
       IPEndPoint ip = new IPEndPoint(IPAddress.Any,9999);
       //no.1
       Socket socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);
       socket.Bind(ip);
       socket.Listen(10);
       Console.WriteLine("Waiting for a client...");
       Socket client = socket.Accept();
       IPEndPoint clientep =(IPEndPoint)client.RemoteEndPoint;
       Console.WriteLine("Connected with {0} at port {1}",clientep.Address, clientep.Port);
       //no.2 & 3
       string welcome = "Welcome";
       byte[] data = new byte[1024];
       data = Encoding.ASCII.GetBytes(welcome);
       //no.4
       client.Send(data, data.Length,SocketFlags.None);
       while(true)
       {
         data = new byte[1024];
         int receivedDataLength = client.Receive(data);
         Console.WriteLine(Encoding.ASCII.GetString(data, 0, receivedDataLength));
         client.Send(data, receivedDataLength, SocketFlags.None);
       }
       Console.WriteLine("Disconnected from {0}",clientep.Address);
       client.Close();
       socket.Close();
    

    我设法理解代码所做的事情直到第4点。但是这段代码:

    
    while(true)
       {
         data = new byte[1024];
         int receivedDataLength = client.Receive(data);
         Console.WriteLine(Encoding.ASCII.GetString(data, 0, receivedDataLength));
         client.Send(data, receivedDataLength, SocketFlags.None);
       }
    

    我不确定上面的代码是做什么的? 对于第5点,有人可以向我解释如何做到这一点吗?这是什么意思,我需要另一个程序作为接收器?

    〜谢谢〜

2 个答案:

答案 0 :(得分:1)

您正在查看的代码是针对echo服务器,该服务器读取由另一个客户端发送到套接字的一些数据,将其打印到控制台,然后将其发送回它来自的客户端。这就是第5点中的代码所做的。这是正在发生的事情:

data = new byte [1024];
这只是分配一个缓冲区来保存我们要读取的数据。

int receivedDataLength = client.Receive(data);
这从套接字接收数据。接收是一个阻塞调用,因此在有数据被读取之前它不会返回,或者直到套接字断开或出现错误,此时它会抛出。 recievedDataLength变量非常重要,因为它告诉我们实际读取了多少字节。读取的字节数可能很容易低于缓冲区的大小,因为我们不知道另一个客户端向套接字发送了多少字节。通过检测读取的字节数,我们可以确定我们知道缓冲区中实际存在多少数据。如果返回0,则表示连接已被另一方关闭。

Console.WriteLine(Encoding.ASCII.GetString(data,0,receivedDataLength));
这只是将缓冲区从任意字节值转换为ASCII字符串。请注意,receivedDataLength允许我们只写出从套接字读取的字节数的字符串。如果我们只是写了整个缓冲区的内容,你就会在控制台上得到随机的废话,因为在receiveDataLenth之后发生的缓冲区中存在的任何数据都是未知的。

client.Send(data,receivedDataLength,SocketFlags.None); 最后,我们通过将数据写入套接字将数据发送回连接的另一端。我们使用receivedDatalength来表示我们只想发送实际读取的字节而不是整个缓冲区。如果您在此处发送不同的消息,则需要使用您要发送的消息的长度(以字节为单位)。你很可能永远不需要设置任何SocketFlags所以不要担心这些。

现在这里的代码是针对想要接收连接的服务器。要建立连接,代码非常相似,除非在调用Socket.Bind(ip)之后,您将调用Socket.Connect(remotehost)而不是Listen()和Accept()。然后将数据写入Socket的代码与上面的步骤5相同。

最后一件事:Socket.Accept()方法起初不直观,所以我会解释它在做什么。调用Listen()告诉套接字允许传入连接,但为了实际使用这些连接,你必须接受它们。 Accept()阻塞直到建立新连接,然后返回一个NEW套接字对象。这个套接字类似于你正在监听的套接字,除了这个套接字代表一个套接字对,这意味着在连接的另一端有另一个类似的套接字,它将与这个套接字进行通信。您应该使用此新套接字与已连接的客户端通信。

从Accept()获得新的Socket后,您仍然拥有旧的套接字,这是您最初调用Accept()的套接字。此套接字仍在侦听新连接,因此如果您希望允许更多计算机连接到此套接字,则需要继续调用Accept(),直到您不再愿意接受连接(如果您不希望接受连接)超过一些任意数量的连接)或直到你想要关闭应用程序。现在我之前说过,Accept()是一个阻塞调用,所以如果你再次调用它,它将不允许你所在的线程做任何其他事情,直到新的连接进入。这意味着你需要做两个中的一个事情:调用BeginAccept以异步方式接受新客户端,或者使用BeginRead或BeginSend异步处理套接字I / O.你不能在同一个线程上做这两件事。执行此操作有点困难,但请查看MSDN上的IPv6Sockets示例(http://msdn.microsoft.com/en-us/library/8sd71sfs(VS.80).aspx),您可以看到如何完成此操作。请记住,绝对有必要不尝试接受新连接并在同一线程上的现有连接上执行I / O.我实际上建议您使用套接字异步执行所有操作。

如果您不想使用所有这些套接字的东西,您还可以查看TcpClient类。它是Socket的一个薄包装器,允许您从TcpClient中获取Stream对象,并从该流中读取/写入。它的使用方式更容易,但它没有Socket那么强大,虽然对于你的应用程序我怀疑你无论如何都需要使用任何花哨的东西,所以我会使用TcpClient。

答案 1 :(得分:0)

它看起来像是在一个循环中接收数据并将其写入控制台,然后回复给发送者。