C ++客户端和C#服务器通过网络流之间的通信

时间:2018-07-30 17:18:05

标签: c# c++ shell networking

我有一个小的shell程序,其中的客户端用c ++编写,服务器用c#编写。客户端应该只向服务器编写一些cmd命令。除了一件事,其他所有东西都工作正常:服务器输出总的红宝石!!

这是C#中的服务器:

1970-01-01

这是c ++中的客户端代码

    static NetworkStream Stream;
    static byte[] AWNSER = new byte[255];

    static void Main(string[] args)
    {
        TcpListener listen = new TcpListener(IPAddress.Any, 123);
        listen.Start();
        Stream = listen.AcceptTcpClient().GetStream();

        Stream.BeginRead(AWNSER, 0, 255, HNDLR, null);
        while (true)
        {
            var str = Console.ReadLine();
            byte[] MESSAGE = Encoding.UTF8.GetBytes(str + "&& cd");
            Stream.Write(MESSAGE, 0, MESSAGE.Length);
        }
    }
    static void HNDLR(IAsyncResult a)
    {
        Stream.EndRead(a);
        Stream.BeginRead(AWNSER, 0, 255, HNDLR, null);

        Console.WriteLine(Encoding.UTF8.GetString(AWNSER));
    }

下面是服务器输出的示例:

FILE *fp;
char AWNSER[255];
WSAData wsaData;
WORD DllVersion = MAKEWORD(2, 1);

if (WSAStartup(DllVersion, &wsaData) != 0) //no error
{
    cout << "Winsock startup failed";
}
SOCKADDR_IN addr;
int addrlen = sizeof(addr);
addr.sin_port = htons(123);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("199.166.177.22");
SOCKET Connection = socket(AF_INET, SOCK_STREAM, NULL);
if (connect(Connection, (SOCKADDR*)&addr, addrlen) != 0)
{   /*ERROR*/
}
else
{
        fp = _popen("dir", "r");
        while (fgets(AWNSER, 255, fp) != NULL) {
            cout << AWNSER;
            send(Connection, AWNSER, 255, NULL);
            AWNSER[255];
        }
        _pclose(fp);
}

非常感谢您的帮助

1 个答案:

答案 0 :(得分:1)

即使没有完全填写,您的客户端也会发送整个AWNSER数组。您应该只发送实际输入的内容。

服务器将输出其接收到的任何内容,但不考虑其实际接收到的字节数。您需要考虑接收到的字节数。

TCP是一种流传输。发送和读取之间没有一对一的关系。因此,您需要缓冲传入的数据,并以某种方式构造数据,以使客户端可以在完成发送消息后发出信号,而服务器可以知道一条完整的消息在哪里结束而下一条从哪里开始。在简单的示例中,空终止符或换行符就足够了。

不显示部分字符串。等待完整的字符串到达​​,然后再显示它。否则,在解码尚未准备好解码的内容时,您就有可能破坏数据。

在服务器处理程序中,请勿在调用Stream.BeginRead()之前先调用Console.WriteLine()。使用AWNSER完成后调用它。否则,AWNSER可能会被覆盖,否则有机会使用它。

尝试更多类似的方法:

服务器:

static NetworkStream Stream;
static MemoryStream Data;
static byte[] AWNSER = new byte[256];

static void Main(string[] args)
{
    TcpListener listen = new TcpListener(IPAddress.Any, 123);
    listen.Start();
    Stream = listen.AcceptTcpClient().GetStream();
    Data = new MemoryStream();
    Stream.BeginRead(AWNSER, 0, AWNSER.Length, HNDLR, null);
    while (true)
    {
        var str = Console.ReadLine();
        byte[] MESSAGE = Encoding.UTF8.GetBytes(str + "&& cd\n");
        Stream.Write(MESSAGE, 0, MESSAGE.Length);
    }
}

static void HNDLR(IAsyncResult a)
{
    int numRead = Stream.EndRead(a);
    if (numRead == 0) return;

    Data.Seek(0, SeekOrigin.End);
    Data.Write(AWNSER, 0, numRead);

    byte[] bytes = Data.GetBuffer();
    int idx = 0;
    int size = (int) Data.Length;

    while (idx < size)
    {
        int found = Array.FindIndex(bytes, idx, size - idx, b => b == 0x0A);
        if (found == -1) break;
        Console.WriteLine(Encoding.UTF8.GetString(AWNSER, idx, found-idx);
        idx = found + 1;
    }

    if (idx > 0)
    {
        Buffer.BlockCopy(bytes, idx, bytes, 0, size - idx);
        Data.SetLength(size - idx);
    }

    Stream.BeginRead(AWNSER, 0, AWNSER.Length, HNDLR, null);
}

客户:

bool sendRaw(SOCKET skt, void *buf, int bufsize)
{ 
    char *p = (char*) buf;
    while (buflen > 0)
    {
        int sent = send(skt, p, buflen, 0);
        if (sent == SOCKET_ERROR) return false;
        p += sent;
        buflen -= sent;
    }
    return true;
}

...

FILE *fp;
char AWNSER[256];
WSAData wsaData;
WORD DllVersion = MAKEWORD(2, 1);

if (WSAStartup(DllVersion, &wsaData) != 0) //no error
{
    cout << "Winsock startup failed";
}

SOCKADDR_IN addr;
int addrlen = sizeof(addr);
addr.sin_port = htons(123);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("199.166.177.22");

SOCKET Connection = socket(AF_INET, SOCK_STREAM, 0);
if (Connection == INVALID_SOCKET)
{
    /*ERROR*/
} 
else
{
    if (connect(Connection, (SOCKADDR*)&addr, addrlen) != 0)
    {
        /*ERROR*/
    }
    else
    {
        fp = _popen("dir", "r");
        while (fgets(AWNSER, 256, fp))
        {
            int len = strlen(AWNSER);
            while ((len > 0) && ((AWNSER[len-1] == '\r') || (AWNSER[len-1] == '\n'))) --len;
            AWNSER[len++] = '\n';
            cout.write(AWNSER, len);
            if (!sendRaw(Connection, AWNSER, len)) break;
        }
        _pclose(fp);
        //... 
    }
    closesocket(Connection);
}