Я пишу службу передачи файлов WCF (net.tcp), которая в конечном итоге разбивает файлы на несколько частей и передает эти части клиенту с сервера / службы. В настоящее время клиент и сервер являются консольными приложениями.
При написании этой услуги я в разное время получал следующее исключение:
System.ServiceModel.CommunicationException: соединение с сокетом было прервано. Это может быть вызвано ошибкой обработки вашего сообщения или превышением тайм-аута приема удаленным хостом, или проблемой основного сетевого ресурса. Тайм-аут локального сокета был «01: 59: 59.4220000».
На самом деле, оно начинается как необработанное исключение: System.Reflection.TargetInvocationException: во время операции произошло исключение, делающее результат недействительным. Проверьте InnerException для подробностей исключения. ---> тогда приведенный выше текст CommunicationException прямо здесь.
В типичной манере Microsoft это сообщение об исключении выходит за рамки бесполезного, поэтому я, наконец, призываю сообщество посмотреть, могу ли я решить эту проблему.
Кроме того, в случае, если это важно, клиент вызывает асинхронно два метода службы (InitGetFilePart () и GetFilePart ()). Согласно моим журналам, первый вызов InitGetFilePartAsync (1, 1) обрабатывается до конца; это означает, что вызывается его обработчик 'Completed', который, в свою очередь, вызывает vcClient.GetFilePartAsync (FileXferCargo, 1), а затем его обработчик порождает поток BackgroundWorker (worker [chunkNum].
RunWorkerAsync (cargoHolder [chunkNum] где chunkNum = 1), который сам завершает работу. Это верно в тот момент, когда я получаю исключение TargetInvocationException, указанное выше.
В прошлом я делал различные изменения (к сожалению, я не могу вспомнить, что именно) в App.config, чтобы исключить это исключение, но теперь ничто из того, что я делаю, кажется, не имеет никакого значения, и я просто НЕ понимаю почему это происходит.
Я прочитал другой совет по этому вопросу, в том числе: «Вы должны отловить исключение на клиенте, прервать текущий прокси-сервер и создать и открыть новый». Я пытался это сделать, но, похоже, мне не удалось поймать это исключение.
Я также читал, что это может быть связано с отправкой слишком большого количества данных по проводной связи, но когда я пытаюсь отправить свой маленький тестовый файл 4k, я получаю то же исключение. Во время моих исследований я также прочитал, что могу вызвать 1 сервисную функцию / метод WCF, много раз используя вызовы * Async () с параметром UserState, что я и делаю.
Я признаю, что являюсь надежным n00b, когда дело доходит до WCF, но я уверен, что мои конфигурационные файлы установлены правильно для того, что я пытаюсь сделать.
Здесь перечислены файлы app.config клиента и сервера, определение интерфейса службы и верхняя часть класса реализации службы.
Клиентский App.config:
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="MyTcpBinding_IFileXferService"
receiveTimeout="02:00:00"
sendTimeout="02:00:00"
transferMode="Streamed"
maxBufferSize="65536"
maxReceivedMessageSize="2147483647">
<readerQuotas maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="65536" />
<security mode="Transport">
<transport clientCredentialType="None">
<extendedProtectionPolicy policyEnforcement="Never" />
</transport>
</security>
</binding>
</netTcpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="ClientConfigBehavior">
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
<clientCredentials>
<serviceCertificate>
<authentication certificateValidationMode="None" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<endpoint name="ClientConfig"
behaviorConfiguration="ClientConfigBehavior"
binding="netTcpBinding"
bindingConfiguration="MyTcpBinding_IFileXferService"
contract="ServiceRefs.IFileXferService" />
</client>
</system.serviceModel>
App.config сервера:
<bindings>
<netTcpBinding>
<!-- Under <netTcpBinding> setting the listenBacklog,
maxConnections, and maxBuffer* values high -->
<binding name="MyTcpBinding_IFileXferService"
receiveTimeout="02:00:00"
sendTimeout="02:00:00"
openTimeout="00:01:00"
transferMode="Streamed"
portSharingEnabled="true"
listenBacklog="32"
maxConnections="64"
maxBufferSize="65536"
maxReceivedMessageSize="2147483646">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</netTcpBinding>
</bindings>
<services>
<service name="MediaServer.LNMediaServerSvc"
behaviorConfiguration="ServerConfigBehavior">
<host>
<baseAddresses>
<add baseAddress="net.tcp://lngsead148191a:9000/fileXferSvc"/>
</baseAddresses>
</host>
<endpoint name="mainEndPoint"
binding="netTcpBinding"
bindingConfiguration="MyTcpBinding_IFileXferService"
contract="ServiceInterfaces.IFileXferService" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServerConfigBehavior">
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceThrottling maxConcurrentCalls="64" />
<dataContractSerializer maxItemsInObjectGraph="2147483646" />
<serviceCredentials>
<serviceCertificate findValue="tp_value"
x509FindType="FindByThumbprint" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Интерфейс службы определяется следующим образом:
[DataContract(IsReference = true)]
public class FileData
{
private long m_startPos;
[DataMember]
public long StartPosition
{
get { return m_startPos; }
set { m_startPos = value; }
}
private long m_endPos;
[DataMember]
public long EndPosition
{
get { return m_endPos; }
set { m_endPos = value; }
}
private byte m_chunkNumber;
[DataMember]
public byte ChunkNumber
{
get { return m_chunkNumber; }
set { m_chunkNumber = value; }
}
private long m_chunkSize;
[DataMember]
public long ChunkSize
{
get { return m_chunkSize; }
set { m_chunkSize = value; }
}
private string md5Hash;
[DataMember]
public string MD5Hash
{
get { return md5Hash; }
set { md5Hash = value; }
}
private string m_destFileSpec;
[DataMember]
public string DestinationFileSpec
{
get { return m_destFileSpec; }
set { m_destFileSpec = value; }
}
private string m_srcFileSpec;
[DataMember]
public string SourceFileSpec
{
get { return m_srcFileSpec; }
set { m_srcFileSpec = value; }
}
private Stream m_sourceStream;
[DataMember]
public Stream SourceStream
{
get { return m_sourceStream; }
set { m_sourceStream = value; }
}
private UInt32 m_JobNo;
[DataMember]
public UInt32 JobNumber
{
get { return m_JobNo; }
set { m_JobNo = value; }
}
private UInt32 m_fileNumber;
[DataMember]
public UInt32 FileNumber
{
get { return m_fileNumber; }
set { m_fileNumber = value; }
}
private long m_fileSize;
[DataMember]
public long FileSize
{
get { return m_fileSize; }
set { m_fileSize = value; }
}
}
[DataContract]
public partial class FileXferCargo
{
private FileData m_fileData;
[DataMember]
public FileData FileData
{
get { return m_fileData; }
set { m_fileData = value; }
}
private bool m_cancelled;
[DataMember]
public bool Cancelled
{
get { return m_cancelled; }
set { m_cancelled = value; }
}
private long m_errorCode;
[DataMember]
public long ErrorCode
{
get { return m_errorCode; }
set { m_errorCode = value; }
}
private Exception m_exceptionObj;
[DataMember]
public Exception Exception
{
get { return m_exceptionObj; }
set { m_exceptionObj = value; }
}
}
[ServiceContract]
public interface IFileXferService
{
[OperationContract]
bool InitFileRequest(ref FileXferCargo fileRequest);
[OperationContract]
bool InitGetFilePart(ref FileXferCargo fileCargo);
[OperationContract]
Stream GetFilePart(FileXferCargo fileCargo);
[OperationContract]
int CloseFile(FileData fileData);
}
Класс реализации Сервиса определяется следующим образом:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,
ConcurrencyMode = ConcurrencyMode.Multiple,
UseSynchronizationContext = false)
]
public class LNMediaServerSvc : IFileXferService
{
...
}