为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
幕布斯6054654 2021-11-07 18:43:14
我有一个小的 shell 程序,其中客户端是用 C++ 编写的,而服务器是用 C# 编写的。客户端应该只向服务器写一些 cmd 命令的 awnseres。除了一件事之外,一切都运行得很完美:服务器输出的都是垃圾!!这是 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));    }这是 C++ 中的客户端代码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 回答

?
牛魔王的故事

TA贡献1830条经验 获得超3个赞

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);

}


查看完整回答
反对 回复 2021-11-07
  • 1 回答
  • 0 关注
  • 339 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信