I'm working on a software i need some help.
I have a client and server. Server will serialize a text file and send it to the client.
My current progress: Client receiving binary array but can't write it to disc as original text file.
private void ListenPort()
{
TcpListener _TcpListener= new _TcpListener(7381);
byte[] received_binary= new byte[1024];
_TcpListener.Start();
while (true)
{
Socket Soket = _TcpListener.AcceptSocket();
Soket.Receive(received_binary, received_binary.Length, 0);
}
}
Do you need to deserialize it to string? Here is a function I wrote a while ago which may help...
public static T BinaryDeserializeObject<T>(byte[] serializedType)
{
if (serializedType == null)
throw new ArgumentNullException("serializedType");
if (serializedType.Length.Equals(0))
throw new ArgumentException("byte array cannot be empty"));
T deserializedObject;
using (MemoryStream memoryStream = new MemoryStream(serializedType))
{
BinaryFormatter deserializer = new BinaryFormatter();
deserializedObject = (T)deserializer.Deserialize(memoryStream);
}
return deserializedObject;
}
The main issue seems to be that you are ignoring the return value from receive. This returns the number of bytes in each read. You should loop until this is non-positive, each time processing (for example writing to a FileStream) that many bytes (only: even if the buffer is larger).
One possible solution is to load the text file either as a series of strings or as a byte array and send that. The byte array approach might be the most concise and efficient, as it can be compressed during send, using the network library networkcomms.net the application calling the sending would look something like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NetworkCommsDotNet;
namespace Client
{
class Program
{
static void Main(string[] args)
{
byte[] bytesToSend = File.ReadAllBytes("testFile.txt");
TCPConnection.GetConnection(new ConnectionInfo("127.0.0.1", 10000)).SendObject("TextFileData", bytesToSend);
Console.WriteLine("Press any key to exit client.");
Console.ReadKey(true);
NetworkComms.Shutdown();
}
}
}
and the server:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NetworkCommsDotNet;
namespace Server
{
class Program
{
static void Main(string[] args)
{
NetworkComms.AppendGlobalIncomingPacketHandler<byte[]>("TextFileData", (packetHeader, connection, incomingData) =>
{
Console.WriteLine("Received TextFileData");
File.WriteAllBytes("testFile.txt", incomingData);
});
TCPConnection.StartListening(true);
Console.WriteLine("Server ready. Press any key to shutdown server.");
Console.ReadKey(true);
NetworkComms.Shutdown();
}
}
}
You will obviously need to download the NetworkCommsDotNet DLL from the website so that you can add it in the 'using NetworkCommsDotNet' reference. Also see the server IP address in the client example is currently "127.0.0.1", this should work if you run both the server and client on the same machine. For more information also checkout the getting started or how to create a client server application articles.
Related
I have an objective to send a pdf file from one server to a REST API which handles some archiving. I am using .NET Core 3.1 and the RestEase API library to help with some of the abstraction.
I have a simple console app that runs at a certain time everyday. The relevant code is as follows:
using System;
using System.Linq;
using System.Threading.Tasks;
using RestEase;
namespace CandidateUploadFile
{
class Program
{
static async Task Main(string[] args)
{
try
{
var apiClientBuilder = new ApiClientBuilder<ITestApi>();
var api = apiClientBuilder.GetApi("https://my.api.com");
var candidate = await api.GetCandidateByEmailAddress("tester#aol.com");
var fileName = "tester.pdf";
var fileBytesToUpload = await FileHelper.GetBytesFromFile($#"./{fileName}");
var result = await api.UploadCandidateFileAsync(fileBytesToUpload, candidate.Data.First().Id, fileName);
}
catch (Exception e)
{
System.Console.WriteLine(e);
}
}
}
}
apiClientBuilder does some auth-header adding, and that's really it. I'm certain that bit isn't relevant.
ITestApi looks like this:
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Models;
using RestEase;
namespace CandidateUploadFile
{
public interface ITestApi : IApi
{
[Get("v1/candidates/{candidateId}")]
Task<Models.Response<Candidate>> GetCandidate([Path] string candidateId);
[Get("v1/candidates")]
Task<Models.Response<IEnumerable<Candidate>>> GetCandidateByEmailAddress([Query] string email);
[Get("v1/candidates")]
Task<Models.Response<IEnumerable<Candidate>>> GetCandidates();
[Post("v1/candidates/{candidateId}/files?perform_as=327d4d21-5cb0-4bc7-95f5-ae43aabc2db7")]
Task<string> UploadFileAsync([Path] string candidateId, [Body] HttpContent content);
[Get("v1/users")]
Task<Models.Response<IEnumerable<User>>> GetUsers();
}
}
It's UploadFileAsync that is really relevant here.
You'll note from Program.Main that I don't explicitly invoke UploadFileAsync. I instead invoke an extension method that basically wraps UploadFileAsync for the purpose of uploading the pdf using a multipart/form-data request. This approach is what comes as a recommendation in the RestEase library docs.. That extension method looks like this:
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
namespace CandidateUploadFile
{
public static class ApiExtension
{
public static async Task<string> UploadCandidateFileAsync(this ITestApi api, byte[] data, string candidateId, string fileName)
{
var content = new MultipartFormDataContent();
var fileContent = new ByteArrayContent(data);
fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "file",
FileName = fileName
};
content.Add(fileContent);
return await api.UploadFileAsync(candidateId, content);
}
}
}
So what will happen when my console app executes is: I will get a successful response from the upload endpoint, and the file on the archive server gets created, but it's blank.
It may be important to know that this does not happen when I send, say, a .txt file. The .txt file will save with the expected content.
Any insight would be helpful. I'm not sure where to start on this one.
Thank you!
The issue was due to what I was doing in my GetBytesFromFile static helper method.
My static helper was using UTF-8 encoding to encode the binary content in the .pdfs I was uploading. However, it was working fine with .txt files I was uploading, which can be expected.
Lesson learned: there is no need -- and makes no sense -- to try to encode binary content before assign it to the multipart/form-data content. I just had to "pass-through" the binary content as-is, more-or-less.
I have program that later needed ability to broadcast an webpage, it basically works, however, only way it can be accessed is from the same machine that program is running on, client says and I agree with him that for our use case there might be need for it to be accessible from other devices in the LAN
The code:
using System;
using System.Net;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var web = new HttpListener();
web.Prefixes.Add("http://localhost:10001/");
web.Start();
var context = web.GetContext();
var response = context.Response;
const string responseString = "<html><body>Hello world</body></html>";
var buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.Length;
var output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
output.Close();
web.Stop();
Console.ReadKey();
}
}
}
I can connect with address localhost:10001, but when using my local IP + :10001 I get
400 BAD REQUEST, invalid hostname
in browser both on same computer and other devices
Ok, maybe just change address mentioned in code to local IP + :10001?
using System;
using System.Net;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var web = new HttpListener();
web.Prefixes.Add("http://192.168.0.12:10001/");
web.Start();
var context = web.GetContext();
var response = context.Response;
const string responseString = "<html><body>Hello world</body></html>";
var buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.Length;
var output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
output.Close();
web.Stop();
Console.ReadKey();
}
}
}
No, when I run it an exception is thrown
access denied
in the line web.Start();
I use Windows 10 Pro x64 and latest Firefox, recently updated solutions .NET version to latest
Yes there have been similar questions but they are way too old to trust and they involve using different Windows tools which isn't best solution for plug and play program, fix in code or pointing out what I have done wrong would be perfect, thanks in advance!
here is my program that i have written
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using System.Data;
namespace ConsoleApplication7
{
class Program
{
static void Main(string[] args)
{
Image img = Image.FromFile("C:\\images.JPG");
byte[] bArr = imgToByteArray(img);
}
public byte[] imgToByteArray(System.Drawing.Image Imagein)
{
byte[] data = null;using (System.IO.MemoryStream ms = new MemoryStream())
{
Imagein.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
data = ms.ToArray();
}
return data;
}
}
}
now when i build the program it shows error
an object reference is required for the non static field, method or property 'Program.imgToByteArray(Image)'
The error is pretty clear, you can't access non static methods in a static context (method).
You have two options to fix this issue.
Option 1
Make your function/method a static function.
public static byte[] imgToByteArray(System.Drawing.Image Imagein)
{
...
}
Option 2:
Create an instance of Program and access the method.
new Program().imgToByteArray(img);
Since you want to print byte array in console (not sure why?) you could do something like this.
Console.WriteLine(string.Join(",", bytearray);
Make the imgToByteArray method static.
There is really no other rational option.
Regarding Option 2 from #Hari Prasad answer you considered an "possible option": You would be creating new class instance to call a member of this instance from a static class member that is the main entry point of the application which is pretty hardcore and given the code design guildelines i.e. https://msdn.microsoft.com/en-us/library/ms245046.aspx it is something you shouldn't.
My application App is using other my application SubApp.
When App needs SubApp it is creating process with SubApp, putting data to SubApp stdin and reading from SubApp stdout.
The problem is that SubApp is using some library which sometimes writes to stdout.
Fragment of SubApp code:
OutsideLibrary.DoSomeInitialization(); // <-- this sometimes writes to stdout
Stream input = Console.OpenStandardInput();
Stream output = Console.OpenStandardOutput();
data = (dataFormat)formatter.Deserialize(input);
//do some job
formatter.Serialize(output, result);
Is there any way to prevent code I don't have from writing to stdout?
Assuming you want to disable third party component output and you have control over the rest of SubApp code you can do following trick: Redirect standard output to null at application bootstrap. When you need to write something to stdout temporary set standard output back to normal, write and set to null again.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace stdio
{
class Program
{
static void Main(string[] args)
{
Console.SetOut(System.IO.TextWriter.Null);
Console.WriteLine("This will go to > null");
WriteOutput("This is written to standard output");
Console.WriteLine("This will also go to > null");
Console.ReadKey();
}
static void WriteOutput(String someString)
{
Console.SetOut(Console.Out);
Stream output = Console.OpenStandardOutput();
StreamWriter sw = new StreamWriter(output);
sw.Write(someString);
sw.Flush();
sw.Close();
output.Close();
Console.SetOut(System.IO.TextWriter.Null);
}
}
}
I've tried this:
StreamWriter sw = new StreamWriter(#"c:\nul");
Console.SetOut(sw);
Console.WriteLine("hello!");
But it throws an exception in new StreamWriter().
The following might work (call it before your external module becomes active):
StreamWriter sw = new StreamWriter(Stream.Null);
Console.SetOut(sw);
A workaround would be to open a real text file and delete it.
I am migrating C# code from using a NetworkStream to SSLStream, however where I use stream.DataAvailable I get the error:
Error 1 'System.Net.Security.SslStream'
does not contain a definition for
'DataAvailable' and no extension
method 'DataAvailable' accepting a
first argument of type
'System.Net.Security.SslStream' could
be found (are you missing a using
directive or an assembly reference?)
now my local MSDN copy does not include DataAvailable as a member of SslStream however http://msdn.microsoft.com/en-us/library/dd170317.aspx says it does have the member DataAvailable.
here is a copy of my code.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Net.Security;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.IO;
namespace Node
{
public static class SSLCommunicator
{
static TcpClient client = null;
static SslStream stream = null;
static List<byte> networkStreamInput = new List<byte>();
public static void connect(string server, Int32 port)
{
try
{
client = new TcpClient(server, port);
stream = new SslStream(client.GetStream(),false);
...
...
...
public static List<DataBlock> getServerInput()
{
List<DataBlock> ret = new List<DataBlock>();
try
{
//check to see if stream is readable.
if (stream.CanRead)
{
//Check to see if there is data available.
if (stream.DataAvailable)
{
byte[] readBuffer = new byte[1024];
int numberOfBytesRead = 0;
//while data is available buffer the data.
do
{
numberOfBytesRead = stream.Read(readBuffer, 0, readBuffer.Length);
byte[] tmp = new byte[numberOfBytesRead];
Array.Copy(readBuffer, tmp, numberOfBytesRead);
networkStreamInput.AddRange(tmp);
} while (stream.DataAvailable);
...
Also if you have a better way to get my output of the stream in to a managed array (there will be some parsing done on it later in the code) I would love the help. I am using Visual Studio 2008
--EDIT
I just realized I linked to the embedded SDK, this is not a embedded system, so how do I see if data is available in the normal .net SDK?
The page you are looking at is for the .NET Micro Framework.
According to this page for .Net 2.0 and this page for .Net 3.5, there is no DataAvailable property on SSLStream.
Edit: Can't you just call Read() and see if you get anything back? i don't think this will block.