我的系统:
服务器: Windows 10 Pro 1511 10586.36 Microsoft Visual Studio 2015社区14.0.24720.00更新1
客户端: Windows 10 IoT核心(版本10586)Raspberry Pi 2.
我的错误:
连接成功建立,但在正常工作几秒钟后丢失。所以数据交换实际上有效,但在Release版本中只有几秒钟,在Debug版本中大约需要40-60秒。
我总是得到:
t.get(); // See code below. Cancelled status.
SocketErrorStatus errorStatus = SocketError::GetStatus(e->HResult);//See code below. errorStatus == 0 (which means Unknown error)
我有时会在客户端出现这些错误,有时在服务器端。
我读了MS示例 - https://code.msdn.microsoft.com/windowsapps/StreamSocket-Sample-8c573931。 我还发现了一些使用SocketStream对象实现异步读/写操作的方法 - https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/DataReaderWriter。
但我无法实现稳定的工作。 以下是代码。
服务器端:
void NetworkHandler::Connect() {
listener->Control->KeepAlive = true;
listener->Control->NoDelay = true;
listener->Control->QualityOfService =
Windows::Networking::Sockets::SocketQualityOfService::LowLatency;
String^ localHostAddr = ref new String(L"192.168.0.10");
HostName^ localHost = ref new HostName(localHostAddr);
String^ localPort = ref new String(L"3001");
create_task(listener->BindEndpointAsync(localHost,
localPort)).then([this, localHost](task<void> previousTask) {
try {
// Try getting an exception.
previousTask.get();
String^ message = "Listening on address " +
localHost->CanonicalName;
}
catch (Platform::Exception^ exception) {
String^ message = "Start listening failed with error: " +
exception->Message;
}
});
listener->ConnectionReceived += ref new
TypedEventHandler<StreamSocketListener^,
StreamSocketListenerConnectionReceivedEventArgs^>(this,
&NetworkHandler::doAccept);
}
void NetworkHandler::doAccept(StreamSocketListener^ listener,
StreamSocketListenerConnectionReceivedEventArgs^ object) {
socket = object->Socket;
reader = ref new DataReader(socket->InputStream);
reader->InputStreamOptions = InputStreamOptions::Partial;
writer = ref new DataWriter(socket->OutputStream);
ifConnected = true;
doRead();
doWrite();
}
void NetworkHandler::doRead() {
task<UINT32>(reader->LoadAsync(sizeof(UINT32))).then([this](UINT32
size) {
if (size < sizeof(UINT32)) {
// The underlying socket was closed before we were able to read
// the whole data.
cancel_current_task();
}
UINT32 dataLength = reader->ReadUInt32();
return task<UINT32>(reader->LoadAsync(dataLength)).then([this,
dataLength](UINT32 actualDataLength) {
if (actualDataLength != dataLength) {
// The underlying socket was closed before we were able to
// read the whole data.
cancel_current_task();
}
});
}).then([this](task<void> t) {
try {
// Try getting all exceptions from the continuation chain above
// this point.
t.get();
//read data here
timer = reader->ReadDouble(); //timer
altitudeASL = reader->ReadDouble(); //altitudeASL
roll = reader->ReadDouble(); //roll
pitch = reader->ReadDouble(); //pitch
yaw = reader->ReadDouble(); //yaw
vCas = reader->ReadDouble(); //vcas
Eng0Rpm = reader->ReadDouble();
Eng1Rpm = reader->ReadDouble();
Eng2Rpm = reader->ReadDouble();
Eng3Rpm = reader->ReadDouble();
doRead(); //call doRead() again after previous call
// successfully ended.
}
catch (Platform::Exception^ e) {
// Explicitly close the socket.
SocketErrorStatus errorStatus =
SocketError::GetStatus(e->HResult);
if (errorStatus != SocketErrorStatus::Unknown) {
switch (errorStatus) {
case SocketErrorStatus::HostNotFound: {
// If hostname from user, this may indicate bad input
// set a flag to ask user to re-enter hostname
break;
}
case SocketErrorStatus::ConnectionRefused: {
// The server might be temporarily busy
break;
}
case SocketErrorStatus::NetworkIsUnreachable: {
// Could be a connectivity issue
break;
}
case SocketErrorStatus::UnreachableHost: {
// Could be a connectivity issue
break;
}
case SocketErrorStatus::NetworkIsDown: {
// Could be a connectivity issue
break;
}
default: {
// Connection failed and no options are available
// Try to use cached data if available
// may want to tell user that connect failed
break;
}
}
}
else {
// got an Hresult that is not mapped to an enum
// Could be a connectivity issue
}
ifConnected = false;
delete socket;
}
catch (task_canceled&) {
// Do not print anything here - this will usually happen
// because user closed the client socket.
// Explicitly close the socket.
ifConnected = false;
delete socket;
}
});
}
void NetworkHandler::doWrite() {
writer->WriteUInt32(4 * sizeof(DOUBLE)); //data size in bytes;
writer->WriteDouble(aileronCmd); // 1-st double, aileron;
writer->WriteDouble(elevatorCmd); //2-nd double, elevator;
writer->WriteDouble(rudderCmd); //3-rd double, rudder;
writer->WriteDouble(throttleCmd); //4-th double, throttle;
UINT32 totalMessageSize = sizeof(UINT32) + 4 * sizeof(DOUBLE);
//total message size
task<UINT32>(writer->StoreAsync()).then([this, totalMessageSize]
(UINT32 writtenBytes) {
if (writtenBytes != totalMessageSize)
cancel_current_task();
}).then([this](task<void> t) {
try {
// Try getting all exceptions from the continuation chain above
this point.
t.get();
doWrite(); //call doWrite() again after previous call
successfully ended.
}
catch (Platform::Exception^ e) {
// Explicitly close the socket.
SocketErrorStatus errorStatus =
SocketError::GetStatus(e->HResult);
if (errorStatus != SocketErrorStatus::Unknown) {
switch (errorStatus) {
case SocketErrorStatus::HostNotFound: {
// If hostname from user, this may indicate bad input
// set a flag to ask user to re-enter hostname
break;
}
case SocketErrorStatus::ConnectionRefused: {
// The server might be temporarily busy
break;
}
case SocketErrorStatus::NetworkIsUnreachable: {
// Could be a connectivity issue
break;
}
case SocketErrorStatus::UnreachableHost: {
// Could be a connectivity issue
break;
}
case SocketErrorStatus::NetworkIsDown: {
// Could be a connectivity issue
break;
}
default: {
// Connection failed and no options are available
// Try to use cached data if available
// may want to tell user that connect failed
break;
}
}
}
else {
// got an Hresult that is not mapped to an enum
// Could be a connectivity issue
}
ifConnected = false;
delete socket;
}
catch (task_canceled&) {
// Do not print anything here - this will usually happen
// because user closed the client socket.
// Explicitly close the socket.
ifConnected = false;
delete socket;
}
});
}
客户方:
void SocketBoard::Connect() {
socket = ref new StreamSocket();
socket->Control->KeepAlive = true;
socket->Control->NoDelay = true;
socket->Control->QualityOfService =
Windows::Networking::Sockets::SocketQualityOfService::LowLatency;
reader = ref new DataReader(socket->InputStream);
reader->InputStreamOptions = InputStreamOptions::Partial;
writer = ref new DataWriter(socket->OutputStream);
String^ remoteHostAddr = ref new String(L"192.168.0.10");
HostName^ remoteHost = ref new HostName(remoteHostAddr);
String^ remotePort = ref new String(L"3001");
create_task(socket->ConnectAsync(remoteHost, remotePort)).get();
ifConnected = true;
TimeSpan period;
period.Duration = 1 * 10000000; // 10,000,000 ticks per second
ThreadPoolTimer^ PeriodicTimer =
ThreadPoolTimer::CreatePeriodicTimer(ref new
TimerElapsedHandler([this](ThreadPoolTimer^ source) {
timer_sec--;
if (timer_sec <= 0)
source->Cancel();
}), period, ref new TimerDestroyedHandler([&](ThreadPoolTimer^ source)
{}));
doRead();
doWrite();
}
SocketBoard::doRead() { //same as Server }
SocketBoard::doWrite() { //same as Server }
我觉得某些东西(内部缓冲区或线程池)被过头了,这会导致异常。
可以请任何人解释一下吗?
答案 0 :(得分:0)
我删除了
reader->InputStreamOptions = InputStreamOptions::Partial;
现在读/写操作正常工作。当我复制
时犯了错误if (actualDataLength != dataLength) {
// The underlying socket was closed before we were able to
// read the whole data.
cancel_current_task();
}
来自MS样本的(在上面的问题中提到)。因此,当读取为PARTIAL时,将调用cancel_current_task(),因此套接字正在关闭,这实际上会强制相反的点(客户端/服务器)抛出。