套接字保持套接字打开,只检查客户端发送的消息

时间:2014-06-27 12:06:49

标签: c# .net sockets

我要做的只是检查客户端发送的消息。 我想要的是维护创建的套接字,并检查客户端不时发送的get消息。

我只使用System.Net.Sockets,我想基于barkeley套接字进行实现。

这是我的代码,

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Runtime.Remoting.Metadata.W3cXsd2001;
namespace Socket_v1._0
{
    class Program
    {
        private const int BUFSIZE = 200;// Size of receive buffer
        private const int BACKLOG = 5; // O valor backlog define o número de pedidos de conexão que podem ser mantidos em espera sem serem aceites pela "system-call" accept.
        static void Main(string[] args)
        {
            int servPort = 8070; //port number

            Socket server = null;
            try
            {
                // Create a socket to accept client connections
                server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                server.Bind(new IPEndPoint(IPAddress.Any, servPort));
                server.Listen(BACKLOG);
            }
            catch (SocketException se)
            {
                Console.WriteLine(se.ErrorCode + ": " + se.Message);
                Environment.Exit(se.ErrorCode);
            }
//for now the server socket is waiting for connections
            byte[] rcvBuffer = new byte[BUFSIZE]; // definir buffer
            int bytesRcvd = 0 ; // numero de bytes recebidos
            for (; ; )
            { // Run forever, accepting and servicing connections
                Socket client = null;
                try
                {

                    client = server.Accept(); // Get client connection
                    Console.Write("Handling client at " + client.RemoteEndPoint + " - ");

                    do {
                        bytesRcvd = client.Receive(rcvBuffer, 0, rcvBuffer.Length, SocketFlags.None);
                        string s = Encoding.ASCII.GetString(rcvBuffer, 0, bytesRcvd);
                        }while (true);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                    client.Close();
                }
            }
        }
      }
    }

所以客户端不时发送http get,我想看到那些消息,

现在第一次运行字符串获取http get,因为我维护套接字打开,我想等待下一条消息(do{}(while(true)))。 它会回到client.receive,并停止。 在检测到来自客户端的另一条消息后,它进入永久循环,字符串为空。

我想要类似聊天的内容,客户端发送消息,服务器显示消息。

因此在打开套接字后,我该怎么做才能从客户端获取消息,然后显示它,然后等待另一条消息?

另一件令我烦恼的事情是客户端http get:

这是http get

GET /iclock/cdata?SN=2182682370001&options=all&pushver=2.1.2&language=80 HTTP/1.1
Host: 192.168.1.43:8070
User-Agent: iClock Proxy/1.09
Connection: close
Accept: * / *

说连接关闭时意味着什么?每次客户端想要发送请求时,我是否需要创建一个新的套接字?

尝试弄明白,我对代码进行了一些更改,在我有这个的时候做了

 while ((bytesRcvd = client.Receive(rcvBuffer/*, 0, rcvBuffer.Length, SocketFlags.None*/)) > 0) 
                    { 
                        totalBytesEchoed += bytesRcvd;
                        string s = Encoding.ASCII.GetString(rcvBuffer, 0, bytesRcvd);
                        Console.WriteLine(s);
                    } 

图像: Wireshark and console app

所以在图像中我有wireshark运行和我的控制台应用程序。

根据wireshark客户端曾试图发送2个http请求,但根据控制台它只显示了一个...

我想显示两个电话..

几年前,我做了一些关于c语言套接字的练习。

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void main(void)
{
  struct sockaddr_in me, from;
  int newSock, sock = socket(AF_INET, SOCK_STREAM, 0);
  int adl = sizeof(me);
  char linha[81];
  bzero((char *) &me, adl);
  me.sin_family = AF_INET;
  me.sin_addr.s_addr = htonl(INADDR_ANY ); /* endereco IP local */
  me.sin_port = htons(8450); /* porta local  */
  if (-1 == bind(sock, (struct sockaddr *) &me, adl))
  {
    close(sock);
    puts("Porta ocupada");
    exit(1);
  }
  listen(sock, 5);
  newSock = accept(sock, (struct sockaddr *) &from, &adl);
  close(sock);
  do
  {
    read(newSock, linha, 81);
    puts(linha);
  } while (strcmp(linha, "exit"));
  close(newSock);
}

这是在c中,所以你可以看到,在接受套接字保持打开后,客户端发送消息,它只在用户发送退出到服务器时关闭套接字... 有时客户端不会发送...但套接字仍处于打开状态,并且当它检测到

这是我想要实现的一个例子,使用system.net.sockets库,,,

感谢

3 个答案:

答案 0 :(得分:1)

有两种套接字:用于侦听的套接字(永远不会连接)和与连接对应的套接字(每个套接字代表一个连接)。

Accept会将连接的套接字返回给刚接受的客户端。每次调用Accept都会接受一个新的独立客户。

如果您希望一次处理多个客户端(几乎总是需要),您必须始终确保对Accept的调用处于待处理状态,以便可以接受新客户端。

实现此目的的一个简单模型是永远接受循环并为您接受的每个客户端启动一个线程:

while (true) {
 var clientSocket = listeningSocket.Accept();
 Task.Factory.StartNew(() => HandleClient(clientSocket));
}

答案 1 :(得分:1)

很可能客户端关闭了连接。

要在服务器端检测到这一点,您需要针对Receive()测试对0的调用结果。

来自MSDN's documentation on Receive()(我强调):

  

如果使用面向连接的Socket,Receive方法将读取尽可能多的数据,最多可达size参数指定的字节数。 如果远程主机使用Shutdown方法关闭套接字连接,并且已收到所有可用数据,接收方法将立即完成并返回字节< /强>

答案 2 :(得分:0)

根据我的经验,每次客户端与服务器/侦听器断开连接时,都会在服务器上注册为SocketException - 客户端强行断开连接。我现在所做的只是试着抓住这个并且&#34; nicelly&#34;忽略它(记录/显示某种消息或运行一个动作来通知用户)。

看看你的代码,稍微重构一下。尝试运行它,看看发生了什么。我添加了一些评论来解释一下。希望这会有所帮助。

.NET中还有一个名为TcpListenner的类,可用于实现所需的行为。

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace SimpleListener
{
    class Program
    {
        const int PORT = 8070;
        const int BACKLOG = 5;

        static Socket socket;
        private static byte[] rcvBuffer;
        private static int bytesRcvd;
        private static string message;

        static void Main(string[] args)
        {
            try
            {
                StartListener();

                Listen();
            }
            catch (Exception ex)
            {
                ShowMessage(ex.Message);
            }
        }

        private static void StartListener()
        {
            try
            {
                //Initialize socket and start listenning
                socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                socket.Bind(new IPEndPoint(IPAddress.Any, PORT));
                socket.Listen(BACKLOG);

                ShowMessage("I'm listenning now..");
            }
            catch (Exception)
            {
                throw;
            }
        }

        private static void Listen()
        {
            try
            {
                rcvBuffer = new Byte[256];
                bytesRcvd = 0;
                message = string.Empty;

                //Start listnening/waiting for client to connect
                while (true)
                {
                    var client = socket.Accept();
                    ShowMessage("Client with IP " + client.RemoteEndPoint.ToString() + " connected!");

                    //Client has connected, keep receiving/displaying data
                    while (true)
                    {
                        SocketError rcvErrorCode;

                        bytesRcvd = 0;
                        message = string.Empty;

                        bytesRcvd = client.Receive(rcvBuffer, 0, rcvBuffer.Length, SocketFlags.None);

                        if (rcvErrorCode != SocketError.Success)
                        {
                            Console.WriteLine("Client with IP " + client.RemoteEndPoint.ToString() + " disconnected!");
                            break;
                        }

                        message = Encoding.ASCII.GetString(rcvBuffer, 0, bytesRcvd);

                        Console.WriteLine(DateTime.Now.ToLongTimeString() + " - " + message);
                    }
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        private static void ShowMessage(string message)
        {
            Console.WriteLine(message);
            Console.WriteLine();
        }
    }
}