gpt4 book ai didi

c# - C++ Client 和 C# Server 通过 Network Stream 通信

转载 作者:行者123 更新时间:2023-11-28 04:35:25 25 4
gpt4 key购买 nike

我有一个小 shell 程序,其中客户端用 C++ 编写,服务器用 C# 编写。客户端应该只向服务器编写一些 awnseres 的 cmd 命令。除了一件事,一切都运行完美:服务器输出完全是垃圾!!

这是 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);
}

这是服务器输出的示例:

 Volumeseriennummer: BAF0-6BB2
Windows


?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

olumeseriennummer: ABF1-7AA3
Windows
??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

olumeseriennummer: ABF1-7AA3
Windows
??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
Verzeichnis von C:\Users\User\Source\MyProblem
?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

erzeichnis von C:\Users\User\Source\MyProblem
?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
30.07.2018 19:08 <DIR> .
myProblem

非常感谢你的帮助

最佳答案

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

服务器正在输出它接收到的任何内容,但不考虑它实际接收到多少字节。您需要考虑接收到的字节数。

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

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

在您的服务器处理程序中,不要在调用 Console.WriteLine() 之前调用 Stream.BeginRead()。使用完 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);
}

关于c# - C++ Client 和 C# Server 通过 Network Stream 通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51599216/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com