MSMQ c++ to c# problem - c#

I want to write messages to a MSMQ queue using C++ and read them using C#.
I send the messages as strings.
It works fine if I both write and read the messages in C++ but if I try to read the message using C#, I get only the first character of the message. (eg: I send "abcd" and I receive only "a").
I also must mention that I am using this code in Windows Mobile.
Here is the c++ code:
HRESULT MSMQManager::WriteMessage(LPWSTR text){
// define the required constants and variables.
const int NUMBEROFPROPERTIES = 5; // number of properties
DWORD cPropId = 0; // property counter
HRESULT hr = MQ_OK; // return code
HANDLE hQueue = NULL; // queue handle
// define an MQMSGPROPS structure.
MQMSGPROPS msgProps;
MSGPROPID aMsgPropId[NUMBEROFPROPERTIES];
MQPROPVARIANT aMsgPropVar[NUMBEROFPROPERTIES];
HRESULT aMsgStatus[NUMBEROFPROPERTIES];
// message label
aMsgPropId[cPropId] = PROPID_M_LABEL;
aMsgPropVar[cPropId].vt = VT_LPWSTR;
aMsgPropVar[cPropId].pwszVal = L"msg";
cPropId++;
// message body
aMsgPropId[cPropId] = PROPID_M_BODY;
aMsgPropVar[cPropId].vt = VT_VECTOR | VT_UI1;
aMsgPropVar[cPropId].caub.pElems = (LPBYTE)text;
aMsgPropVar[cPropId].caub.cElems = wcslen(text)*2;
cPropId++;
// message body type
aMsgPropId[cPropId] = PROPID_M_BODY_TYPE;
aMsgPropVar[cPropId].vt = VT_UI4;
aMsgPropVar[cPropId].ulVal = VT_LPWSTR;
cPropId++;
// initialize the MQMSGPROPS structure.
msgProps.cProp = cPropId;
msgProps.aPropID = aMsgPropId;
msgProps.aPropVar = aMsgPropVar;
msgProps.aStatus = aMsgStatus;
// Call MQSendMessage to send the message to the queue.
hr = MQSendMessage(
this->writeHandle, // Queue handle
&msgProps, // Message property structure
MQ_NO_TRANSACTION // Not in a transaction
);
Here is the c# code:
public string ReadMessageUnformatted()
{
try
{
Message received;
Stream bodyStream = null;
StreamReader sr = null;
char[] buffer = new char[256];
received = this.readMQ.Receive();
bodyStream = received.BodyStream;
sr = new StreamReader(bodyStream);
//this.lastReceived = sr.ReadLine();
sr.Read(buffer, 0, 256);
this.lastReceived = new string(buffer);
return lastReceived;
}
catch (Exception exc)
{
MessageBox.Show(exc.ToString(), "Exception");
return null;
}
}
I am using BodyStream instead of Body for the message because I don't want to use any message formatter.
Thanks

I solved myself the problem. I shall post here the code maybe there is someone else interested.
try
{
Message received;
Stream bodyStream = null;
int bufLength = 512;
byte[] buffer = new byte[bufLength];
received = this.readMQ.Receive();
bodyStream = received.BodyStream;
bodyStream.Read(buffer, 0, bufLength);
this.lastReceived = Encoding.Unicode.GetString(buffer, 0, buffer.Length);
return lastReceived;
}
catch (Exception exc)
{
MessageBox.Show(exc.ToString(), "Exception");
return null;
}

Maybe you can try:
aMsgPropVar[cPropId].ulVal = VT_BSTR;
VT_BSTR is used to indicate a unicode string.
VT_LPWSTR needs to be null-terminated, which I don't think your string is.

Related

SkipLastField called on an end-group tag. GoogleProtobuf (C# and C++)

I'm trying to serialize a message in C++ using Google proto, send it through a TCP socket and finally receive and parse it in a C# client.
I keep getting the following exception on the C# google proto parser:
SkipLastField called on an end-group tag, indicating that the corresponding start-group was missing
I printed the Serialized Input Stream both before sending and after receiving and it perfectly matches on both ends.
C# Listener/Deserializer
namespace NetStreamHandler
{
public class Server
{
public static void ReceiveData()
{
var ipAddress = IPAddress.Parse("127.0.0.1");
var listener = new TcpListener(ipAddress, 20511);
listener.Start();
listener.BeginAcceptSocket(MessageReceived, listener);
}
private static void MessageReceived(IAsyncResult result)
{
var server = (TcpListener)result.AsyncState;
using (var client = server.EndAcceptTcpClient(result))
using (var stream = client.GetStream())
{
try
{
var cod = new CodedInputStream(stream);
var packet = Serialize.Parser.ParseFrom(cod);
Console.WriteLine($"Message: {packet.ToString()}");
}
catch (Exception ex)
{
Console.WriteLine($"Exception Caught at: {ex.Message}\n");
}
}
}
}
}
C++ Send/Serialize
int bCount;
Serialized::Serialize pLoad;
pLoad.set_command("Test");
pLoad.set_id(10);
pLoad.set_num(3);
pLoad.set_packettype(1);
pLoad.set_ret("Test");
printf("Size after serializing: %d bytes\n", pLoad.ByteSize());
auto size = pLoad.ByteSize();
auto packet = new char[size];
ArrayOutputStream ArrayOut(packet, size);
auto coutput = new CodedOutputStream(&ArrayOut);
coutput->WriteVarint32(pLoad.ByteSize());
pLoad.SerializeToCodedStream(coutput);
auto sConnect = SetupSocket();
if (!sConnect) { printf("Socket failure\n"); goto DONE; }
std::cout << "Buffer:" << byte_2_str(packet, size) << std::endl;
bCount = send(sConnect, packet, size, 0);
if(bCount == SOCKET_ERROR)
{
fprintf(stderr, "Server: send() failed: error %d: %s\n", WSAGetLastError(), DecodeError(WSAGetLastError()));
goto DONE;
}
else if (bCount == -1) {
fprintf(stderr, "Error sending data %d\n", errno);
goto DONE;
}
else {
printf("Sent bytes %d\n", bCount);
}
DONE:
closesocket(sConnect);
printf("All done..\n");
You have allocated only payload size bytes for the buffer used in the ArrayOut that is bound to the CodedOutputStream. But you tried to write slightly more (payload size + size of (Varint32). Guess you need to have buffer large enough to store payload with message length.
I use Poco framework. Here is c++ example code below:
void writeDelimitedTo(const google::protobuf::MessageLite& message, Poco::Net::StreamSocket& socket) {
int totalMsgSize = message.ByteSize()+4; // Variant32 length 1-4
char *buf = new char [totalMsgSize];
ArrayOutputStream aos(buf, totalMsgSize);
CodedOutputStream coded_output(&aos);
coded_output.WriteVarint32(message.ByteSize());
message.SerializeToCodedStream(&coded_output);
socket.sendBytes(buf, coded_output.ByteCount());
delete buf;
}
And of course c# part just using System.Io.Stream as clientStream. ProtoMsgStructRequest, and ProtoMsgStructResponse are ProtoBuf messages:
using (var pbReader = new Google.Protobuf.CodedInputStream(clientStream, true))
{
var inRequest = new ProtoMsgStructRequest();
pbReader.ReadMessage(inRequest);
{
var outResponse = new ProtoMsgStructResponse();
using (var pbWriter = new Google.Protobuf.CodedOutputStream(clientStream, true))
{
pbWriter.WriteMessage(outResponse);
}
}
}

UsbBulkInPipe doesn't return the actual values

I am using UsbBulkInPipe to obtain data from my USB device. When I read data the length is correct but value are all zeros. How I can read the real data?
This is what I've tried:
UInt32 bytesRead = 0;
UsbBulkInPipe bulkIn = device.DefaultInterface.BulkInPipes[0];
var stream = bulkIn.InputStream;
DataReader reader = new DataReader(stream);
try
{
bytesRead = await reader.LoadAsync(bulkIn.EndpointDescriptor.MaxPacketSize);
}
catch (Exception exception)
{
//ShowStatus(exception.Message.ToString());
}
finally
{
byte[] value = new byte[bytesRead];
reader.ReadBytes(value);
}
At the moment I am using this method:
var t = reader.LoadAsync(buf.MaxPacketSize).AsTask(cancellationTokenSourceBulkIn.Token);
uint len = t.Result;
byte[] data = reader.ReadBuffer(len).ToArray();

Sending large objects over TCP: "End of Stream encountered before parsing was completed"

I keep getting an SerializationException whenever I try to deserialize a list of doubles from a NetworkStream:
End of Stream encountered before
parsing was completed
I have a simple client server architecture: my TcpTransportClient wraps the functionality of a TcpClient and I utilize two basic methods: Send (sends a message) and Receive (blocks until a message is received).
The Send function takes a Message, serializes it using a BinaryFormatter and sends the bytes via the NetworkStream.
public void Send(Message message)
{
if (message == null)
{
throw new TransportException("Invalidate Parameter In Send Call");
}
if (_tcpClient == null || !_tcpClient.Connected)
{
throw new TransportException("Client Not Connected");
}
lock (_sync)
{
// Serialzie the message
MemoryStream memStream = new MemoryStream();
_serializer.Serialize(memStream, message);
// Get the bytes of of the memory stream
byte[] buffer = memStream.GetBuffer();
// Write the message to the network stream
NetworkStream networkStream = _tcpClient.GetStream();
networkStream.Write(buffer, 0, buffer.Length);
networkStream.Flush();
}
}
The receive function reads bytes into a buffer from the NetworkStream, then deserializes the message by using a BinaryFormatter:
public Message Receive()
{
if (_tcpClient == null || !_tcpClient.Connected)
{
throw new TransportException("Client Not Connected");
}
byte[] buffer;
MemoryStream memStream = new MemoryStream();
NetworkStream netStream = _tcpClient.GetStream();
try
{
do
{
// Allocate a new buffer
buffer = new byte[_tcpClient.ReceiveBufferSize];
// Read the message buffer
int sizeRead = netStream.Read(buffer, 0, buffer.Length);
// Write the buffer to the memory stream
memStream.Write(buffer, 0, sizeRead);
} while (netStream.DataAvailable);
// Reset the memory stream position
memStream.Position = 0;
// Deserialize the message
object tmp = _deserializer.Deserialize(memStream); // <-- The exception is here!
// Cast the object to a message
return (Message)tmp;
}
catch (System.Exception e)
{
if (_tcpClient == null || !_tcpClient.Connected)
{
throw new TransportException("Client Not Connected");
}
else
{
throw e;
}
}
}
I have a basic sending thread:
TcpTransportClient client = new TcpTransportClient(GetLocalAddress(), servicePort);
client.Connect();
Thread sendThread = new Thread(() =>
{
List<double> dataSet = new List<double>();
for (double d = 0.0; d < 500.0; d++)
{
dataSet.Add(d);
}
while (true)
{
try
{
// Serialize the data set
MemoryStream memStream = new MemoryStream();
BinaryFormatter binFormat = new BinaryFormatter();
binFormat.Serialize(memStream, (object)dataSet);
// Create a message
Message msg = new Message();
// Hold the object bytes in an opaque field
msg.SetFieldValue(1000, memStream.GetBuffer());
// Set the message topic
msg.SetTopic("client.dataSet");
// Send the message
client.Send(msg);
// Sleep
Thread.Sleep(3000);
}
catch (TransportException)
{
break;
}
catch(Exception)
{
//ignore it
}
}
});
sendThread.IsBackground = true;
sendThread.Start();
And a receive thread which gets started whenever a TcpClient is accepted:
public void HandleAcceptedClient(TcpTransportClient client)
{
Thread receiveThread = new Thread(() =>
{
while (true)
{
try
{
Message msg = client.Receive();
Trace.WriteLine("Server Received: " + msg.GetTopic());
byte[] buffer = msg.GetFieldOpaqueValue(1000);
MemoryStream memStream = new MemoryStream(buffer);
BinaryFormatter binFormat = new BinaryFormatter();
List<double> dataSet = (List<double>)binFormat.Deserialize(memStream);
if (dataSet.Count == 500)
{
Trace.WriteLine(DateTime.Now + ": OK");
}
else
{
Trace.WriteLine(DateTime.Now + ": FAIL");
}
}
catch (TransportException)
{
break;
}
catch(Exception)
{
// ignore it
}
}
});
receiveThread.IsBackground = true;
receiveThread.Start();
}
The exception always occurs when I try to deserialize the message in Receive method of my TcpTransportClient, but the problem only occurs if I put some data in the data set. What's the proper way to send a list of values over a network and successfully deserialize them on the receiving end?
P.S. I tried the solution in a nearly identical question, but it didn't work: I'm still getting the same exception.
while (netStream.DataAvailable);
That's not correct. You should stop reading when the Read() call returns 0. The DataAvailable property just tells you whether or not the Read() call will block, waiting to allow the server to catch up.
You need message framing.

Frustrating TCP Serialization Exception: Binary stream '0' does not contain a valid BinaryHeader

I posted a question on how to send large objects over TCP and it seems like the primary issue is solved, but now frequently I get another exception:
Binary stream '0' does not contain a
valid BinaryHeader. Possible causes
are invalid stream or object version
change between serialization and
deserialization.
The issue is still in my Receive method:
public Message Receive()
{
if (_tcpClient == null || !_tcpClient.Connected)
{
throw new TransportException("Client Not Connected");
}
// buffers
byte[] msgBuffer;
byte[] sizeBuffer = new byte[sizeof(int)];
// bites read
int readSize = 0;
// message size
int size = 0;
MemoryStream memStream = new MemoryStream();
NetworkStream netStream = _tcpClient.GetStream();
BinaryFormatter formatter = new BinaryFormatter();
try
{
// Read the message length
netStream.Read(sizeBuffer, 0, sizeof(int));
// Extract the message length
size = BitConverter.ToInt32(sizeBuffer, 0);
msgBuffer = new byte[size];
// Fill up the message msgBuffer
do
{
// Clear the buffer
Array.Clear(msgBuffer, 0, size);
// Read the message
readSize += netStream.Read(msgBuffer, 0, _tcpClient.ReceiveBufferSize);
// Write the msgBuffer to the memory streamvb
memStream.Write(msgBuffer, 0, readSize);
} while (readSize < size);
// Reset the memory stream position
memStream.Position = 0;
// Deserialize the message
return (Message)formatter.Deserialize(memStream); // <-- Exception here
}
catch (System.Exception e)
{
if (_tcpClient == null || !_tcpClient.Connected)
{
throw new TransportException("Client Not Connected");
}
else
{
throw e;
}
}
}
The rest of the code relevant to this example can be found in my original question.
Does anybody know what is causing this exception and how I can avoid it?
Update
Changed the Read to read a maximum of _tcpClient.ReceiveBufferSize bytes at a time, rather than trying to read the full message size (which can be larger than the buffer size) and while the frequency of the Exception decreased slightly, it's still occurring quite often.
Let me suggest you a slight simplification of your code:
public Message Receive()
{
try
{
if (_tcpClient == null || !_tcpClient.Connected)
{
throw new TransportException("Client Not Connected");
}
using (var stream = _tcpClient.GetStream())
using (var reader = new BinaryReader(stream))
{
int size = reader.ReadInt32();
byte[] buffer = reader.ReadBytes(size);
using (var memStream = new MemoryStream(buffer))
{
var formatter = new BinaryFormatter();
return (Message)formatter.Deserialize(memStream);
}
}
}
catch (System.Exception e)
{
if (_tcpClient == null || !_tcpClient.Connected)
{
throw new TransportException("Client Not Connected");
}
throw e;
}
}
Also if you are doing this for fun and/or education purposes then it's ok, but in a real project you should probably consider WCF in order to transmit objects over the wire.
WCF not so good in client-server. Th polling duplex is quite raw technology.

File using .net sockets, transferring problem

I have a client and server, client sending file to server. When i transfer files on my computer(in local) everything is ok(try to sen file over 700mb).
When i try to sent file use Internet to my friend in the end of sending appears error on server "Input string is not in correct format".This error appears in this expression fSize = Convert::ToUInt64(tokenes[0]); - and i don't mind wht it's appear. File should be transfered and wait other transferring
ps: sorry for too much code, but i want to find solution
private: void CreateServer()
{
try{
IPAddress ^ipAddres = IPAddress::Parse(ipAdress);
listener = gcnew System::Net::Sockets::TcpListener(ipAddres, port);
listener->Start();
clientsocket =listener->AcceptSocket();
bool keepalive = true;
array<wchar_t,1> ^split = gcnew array<wchar_t>(1){ '\0' };
array<wchar_t,1> ^split2 = gcnew array<wchar_t>(1){ '|' };
statusBar1->Text = "Connected" ;
//
while (keepalive)
{
array<Byte>^ size1 = gcnew array<Byte>(1024);
clientsocket->Receive(size1);
System::String ^notSplited = System::Text::Encoding::GetEncoding(1251)->GetString(size1);
array<String^> ^ tokenes = notSplited->Split(split2);
System::String ^fileName = tokenes[1]->ToString();
statusBar1->Text = "Receiving file" ;
unsigned long fSize = 0;
//IN THIS EXPRESSIN APPEARS ERROR
fSize = Convert::ToUInt64(tokenes[0]);
if (!Directory::Exists("Received"))
Directory::CreateDirectory("Received");
System::String ^path = "Received\\"+ fileName;
while (File::Exists(path))
{
int dotPos = path->LastIndexOf('.');
if (dotPos == -1)
{
path += "[1]";
}
else
{
path = path->Insert(dotPos, "[1]");
}
}
FileStream ^fs = gcnew FileStream(path, FileMode::CreateNew, FileAccess::Write);
BinaryWriter ^f = gcnew BinaryWriter(fs);
//bytes received
unsigned long processed = 0;
pBarFilesTr->Visible = true;
pBarFilesTr->Minimum = 0;
pBarFilesTr->Maximum = (int)fSize;
// Set the initial value of the ProgressBar.
pBarFilesTr->Value = 0;
pBarFilesTr->Step = 1024;
//loop for receive file
array<Byte>^ buffer = gcnew array<Byte>(1024);
while (processed < fSize)
{
if ((fSize - processed) < 1024)
{
int bytes ;
array<Byte>^ buf = gcnew array<Byte>(1024);
bytes = clientsocket->Receive(buf);
if (bytes != 0)
{
f->Write(buf, 0, bytes);
processed = processed + (unsigned long)bytes;
pBarFilesTr->PerformStep();
}
break;
}
else
{
int bytes = clientsocket->Receive(buffer);
if (bytes != 0)
{
f->Write(buffer, 0, 1024);
processed = processed + 1024;
pBarFilesTr->PerformStep();
}
else break;
}
}
statusBar1->Text = "File was received" ;
array<Byte>^ buf = gcnew array<Byte>(1);
clientsocket->Send(buf,buf->Length,SocketFlags::None);
f->Close();
fs->Close();
SystemSounds::Beep->Play();
}
}catch(System::Net::Sockets::SocketException ^es)
{
MessageBox::Show(es->ToString());
}
catch(System::Exception ^es)
{
MessageBox::Show(es->ToString());
}
}
private: void CreateClient()
{
clientsock = gcnew System::Net::Sockets::TcpClient(ipAdress, port);
ns = clientsock->GetStream();
sr = gcnew StreamReader(ns);
statusBar1->Text = "Connected" ;
}
private:void Send()
{
try{
OpenFileDialog ^openFileDialog1 = gcnew OpenFileDialog();
System::String ^filePath = "";
System::String ^fileName = "";
//file choose dialog
if (openFileDialog1->ShowDialog() == System::Windows::Forms::DialogResult::OK)
{
filePath = openFileDialog1->FileName;
fileName = openFileDialog1->SafeFileName;
}
else
{
MessageBox::Show("You must select a file", "Error",
MessageBoxButtons::OK, MessageBoxIcon::Exclamation);
return;
}
statusBar1->Text = "Sending file" ;
NetworkStream ^writerStream = clientsock->GetStream();
System::Runtime::Serialization::Formatters::Binary::BinaryFormatter ^format =
gcnew System::Runtime::Serialization::Formatters::Binary::BinaryFormatter();
array<Byte>^ buffer = gcnew array<Byte>(1024);
FileStream ^fs = gcnew FileStream(filePath, FileMode::Open);
BinaryReader ^br = gcnew BinaryReader(fs);
//file size
unsigned long fSize = (unsigned long)fs->Length;
//transfer file size + name
bFSize = Encoding::GetEncoding(1251)->GetBytes(Convert::ToString(fs->Length+"|"+fileName+"|"));
writerStream->Write(bFSize, 0, bFSize->Length);
//status bar
pBarFilesTr->Visible = true;
pBarFilesTr->Minimum = 0;
pBarFilesTr->Maximum = (int)fSize;
pBarFilesTr->Value = 0; // Set the initial value of the ProgressBar.
pBarFilesTr->Step = 1024;
//bytes transfered
unsigned long processed = 0;
int bytes = 1024;
//loop for transfer
while (processed < fSize)
{
if ((fSize - processed) < 1024)
{
bytes = (int)(fSize - processed);
array<Byte>^ buf = gcnew array<Byte>(bytes);
br->Read(buf, 0, bytes);
writerStream->Write(buf, 0, buf->Length);
pBarFilesTr->PerformStep();
processed = processed + (unsigned long)bytes;
break;
}
else
{
br->Read(buffer, 0, 1024);
writerStream->Write(buffer, 0, buffer->Length);
pBarFilesTr->PerformStep();
processed = processed + 1024;
}
}
array<Byte>^ bufsss = gcnew array<Byte>(100);
writerStream->Read(bufsss,0,bufsss->Length);
statusBar1->Text = "File was sent" ;
btnSend->Enabled = true;
fs->Close();
br->Close();
SystemSounds::Beep->Play();
newThread->Abort();
}
catch(System::Net::Sockets::SocketException ^es)
{
MessageBox::Show(es->ToString());
}
}
UPDATE: 2Ben Voigt - ok, i can add checking if clientsocket->Receive(size1); equal zero, but why he begin receiving data again , in the ending of receiving.
UPDATE:After adding this checking problem remains. AND WIN RAR SAY TO OPENING ARCHIVE - unexpected end of file!
UPDATE:2Kevin - http://img153.imageshack.us/img153/3760/erorr.gif
I think it continue receiving some bytes from client(that remains in the stream), but why? - exists cycle while (processed < fSize)
UPDATE: 2Ben Voigt -i did this fix processed += bytes; and file transfered successfully.Thanks!
I am not very good with english and I don't understand what you mean when said "Consider what happens if your initial read snags part of the file data..." What means snags? And what initial data do you mean?
Don't ignore the return value from clientsocket->Receive(size1).
DOC: "Socket.Receive Method (Byte[])"
EDIT: Consider what happens if your initial read snags part of the file data. Also consider what happens if your last read (which for some reason is still 1024 bytes instead of the remaining byte count) snags part of the header for the next request.
EDIT: You also haven't yet done anything useful with the return value from Receive. Your line of code:
processed = processed + 1024;
needs to be
processed += bytes;
EDIT: "snags" means "captures" or "grabs"
You have:
clientsocket->Receive(size1);
and a little later:
clientsocket->Receive(buf);
and you assume that all the header data is in size1 and all the file data is in buf. That's not a safe assumption on a stream socket. Datagram sockets preserve message boundaries, stream sockets like TCP do not. In fact, Nagle's algorithm might even cause the first part of the file data to be put into the same network packet as the header, but even if it doesn't, the receiver's TCP stack throws away the packet boundaries and just puts things into one big receive buffer.

Categories

Resources