I need to help, I want to make server and client, who will communicate together.(send/receive data)
Example: client sends username and password to server when I login and server checks it and sends (correct or not correct) to client.
Server and client can send and receive data, and more data together (for example: username, password ... in one communication)
I need from you the best example of communicating with the client, server, currently I have this script by youtube: enter link description here
There is send / receive method from youtube:
public class PacketWriter : BinaryWriter
{
// This will hold our packet bytes.
private MemoryStream _ms;
// We will use this to serialize (Not in this tutorial)
private BinaryFormatter _bf;
public PacketWriter() : base()
{
// Initialize our variables
_ms = new MemoryStream();
_bf = new BinaryFormatter();
// Set the stream of the underlying BinaryWriter to our memory stream.
OutStream = _ms;
}
public void Write(Image image)
{
var ms = new MemoryStream(); //Create a memory stream to store our image bytes.
image.Save(ms, ImageFormat.Png); //Save the image to the stream.
ms.Close(); //Close the stream.
byte[] imageBytes = ms.ToArray(); //Grab the bytes from the stream.
//Write the image bytes to our memory stream
//Length then bytes
Write(imageBytes.Length);
Write(imageBytes);
}
public void WriteT(object obj)
{
//We use the BinaryFormatter to serialize our object to the stream.
_bf.Serialize(_ms, obj);
}
public byte[] GetBytes()
{
Close(); //Close the Stream. We no longer have need for it.
byte[] data = _ms.ToArray(); //Grab the bytes and return.
return data;
}
}
public class PacketReader : BinaryReader
{
// This will be used for deserializing
private BinaryFormatter _bf;
public PacketReader(byte[] data) : base(new MemoryStream(data))
{
_bf = new BinaryFormatter();
}
public Image ReadImage()
{
//Read the length first as we wrote it.
int len = ReadInt32();
//Read the bytes
byte[] bytes = ReadBytes(len);
Image img; //This will hold the image.
using (MemoryStream ms = new MemoryStream(bytes))
{
img = Image.FromStream(ms); //Get the image from the stream of the bytes.
}
return img; //Return the image.
}
public T ReadObject<T>()
{
//Use the BinaryFormatter to deserialize the object and return it casted as T
/* MSDN Generics
* http://msdn.microsoft.com/en-us/library/ms379564%28v=vs.80%29.aspx
*/
return (T)_bf.Deserialize(BaseStream);
}
}
I don't know if it is better method, I don't have experience with it, so I want to ask someone more experienced.
Is good method make images from data and send?
Thank you for any advice, I will be grateful!
Check out this CodeProject example, it seems to be what you're looking for. You'll need two separate applications, one for your server and the other for your client.
Server: Essentially all you need to do here is open up a TcpListener and receive the bytes from it. From the CodeProject article:
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
public class serv {
public static void Main() {
try {
IPAddress ipAd = IPAddress.Parse("172.21.5.99");
// use local m/c IP address, and
// use the same in the client
/* Initializes the Listener */
TcpListener myList=new TcpListener(ipAd,8001);
/* Start Listening at the specified port */
myList.Start();
Console.WriteLine("The server is running at port 8001...");
Console.WriteLine("The local End point is :" +
myList.LocalEndpoint );
Console.WriteLine("Waiting for a connection.....");
Socket s = myList.AcceptSocket();
Console.WriteLine("Connection accepted from " + s.RemoteEndPoint);
byte[] b=new byte[100];
int k=s.Receive(b);
Console.WriteLine("Recieved...");
for (int i=0;i<k;i++)
Console.Write(Convert.ToChar(b[i]));
ASCIIEncoding asen=new ASCIIEncoding();
s.Send(asen.GetBytes("The string was recieved by the server."));
Console.WriteLine("\nSent Acknowledgement");
s.Close();
myList.Stop();
}
catch (Exception e) {
Console.WriteLine("Error..... " + e.StackTrace);
}
}
}
Client: The client is pretty similar, except instead of using a TcpListener, you'd use a TcpClient. Again from CodeProject:
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Net.Sockets;
public class clnt {
public static void Main() {
try {
TcpClient tcpclnt = new TcpClient();
Console.WriteLine("Connecting.....");
tcpclnt.Connect("172.21.5.99",8001);
// use the ipaddress as in the server program
Console.WriteLine("Connected");
Console.Write("Enter the string to be transmitted : ");
String str=Console.ReadLine();
Stream stm = tcpclnt.GetStream();
ASCIIEncoding asen= new ASCIIEncoding();
byte[] ba=asen.GetBytes(str);
Console.WriteLine("Transmitting.....");
stm.Write(ba,0,ba.Length);
byte[] bb=new byte[100];
int k=stm.Read(bb,0,100);
for (int i=0;i<k;i++)
Console.Write(Convert.ToChar(bb[i]));
tcpclnt.Close();
}
catch (Exception e) {
Console.WriteLine("Error..... " + e.StackTrace);
}
}
}
This is a very basic example of how you can do some simple networking tasks in .Net; if you're planning on creating web-based applications I'd recommend you use WCF/Asp.Net.
Related
So I'm aiming to write a little multiplayer game but first I'm working on getting a server/client architecture setup that can just send simple messages to oneanother using Sockets and JSON.
Rather quickly I've encountered an issue that when a sender sends two messages in rapid succession the receiver receives them as part of the same stream, even though they are seperated by flushes.
The entire Connection class looks like this, it is used by both the sender and receiver:
namespace Networking
{
public class Connection
{
JsonSerializerSettings jsonSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.Auto };
private Socket socket;
private NetworkStream stream;
/// <summary>
/// Make a connection with a stream from a socket.
/// </summary>
public Connection(Socket socket)
{
stream = new NetworkStream(socket);
}
public void Close()
{
stream.Close();
socket.Close();
stream.Dispose();
socket.Dispose();
}
private object writeLock = new object();
public void Write(Request request)
{
lock (writeLock)
{
using (var memoryStream = new MemoryStream())
{
Message message = new Message(null, Messaging.Enums.MessageType.Connect, request);
string json = JsonConvert.SerializeObject(message, jsonSettings);
stream.Write(Encoding.ASCII.GetBytes(json));
stream.Flush();
}
}
}
public Message Read()
{
byte[] data = new byte[1024];
using (MemoryStream ms = new MemoryStream())
{
do
{
int numBytesRead = stream.Read(data, 0, data.Length);
ms.Write(data, 0, numBytesRead);
}
while (stream.DataAvailable);
ms.Seek(0, SeekOrigin.Begin);
StreamReader sr = new StreamReader(ms);
string json = sr.ReadToEnd();
return JsonConvert.DeserializeObject<Message>(json, jsonSettings);
}
}
}
}
The incoming data and error looks like this:
I suppose this question isn't 100% specific to C# and .NET but more about how to deal with this problem with sockets in general. Looking for some guidance thanks!
I'm trying to send files after sending their's information via TCP connection. At the end of receiver host, the data packets are received. I used Wireshark to confirm it. However the data couldn't be received in NetworkStream.
public class FileTransporter
{
public void ReceiveFiles(IPAddress IP, int port)
{
TcpListener tcpListener = new TcpListener(IP, port);
tcpListener.Start();
using (TcpClient tcpClient = tcpListener.AcceptTcpClient())
{
if (tcpClient.Connected)
{
using (NetworkStream networkStream = tcpClient.GetStream())
{
int pointer = 0;
byte[] fileNameLengthBytes = new byte[sizeof(int)];
networkStream.Read(fileNameLengthBytes, pointer, fileNameLengthBytes.Length);
int fileNameLength = BitConverter.ToInt32(fileNameLengthBytes, pointer);
// code to read fileName and it's size
networkStream.Close();
}
}
tcpClient.Close();
}
tcpListener.Stop();
}
public void SendFiles(IPAddress IP, int port, string[] paths)
{
for(int i=0; i<paths.Length; i++)
{
FilePackage filePackage = new FilePackage(paths[i]);
byte[] infoBytes = filePackage.EncodeInfoToByte();
using (TcpClient tcpClient = new TcpClient())
{
tcpClient.Connect(IP, port);
using (NetworkStream networkStream = tcpClient.GetStream())
{
networkStream.Write(infoBytes, 0, infoBytes.Length);
networkStream.Close();
}
tcpClient.Close();
}
}
}
}
public class FilePackage
{
public FilePackage(string fileName)
{
this.Info = new FileInfo(fileName);
}
public byte[] EncodeInfoToByte()
{
List<byte> infoByte = new List<byte>();
infoByte.AddRange(BitConverter.GetBytes(this.Info.Name.Length));
infoByte.AddRange(Encoding.UTF8.GetBytes(this.Info.Name));
infoByte.AddRange(BitConverter.GetBytes(this.Info.Length));
return infoByte.ToArray();
}
I am going to Assume that ReadFiles is invoked somehow / somewhere else.
I have a very similar implementation, however my "Read" of the stream is much smaller:
// Read the first batch of the TcpServer response bytes.
var bytes = new byte[512];
// Loop to receive all the data sent by the Server.
var sb = new StringBuilder();
do
{
var i = stream.Read(bytes, 0, bytes.Length);
sb.AppendFormat("{0}", Encoding.ASCII.GetString(bytes, 0, i));
} while (stream.DataAvailable);
Perhaps using "stream.DataAvailable" will allow you to test for data existence and that way you can make sure that you only process when data is available.
Also I don't see where "pointer" is being initialized in your code.
If it is not set to 0 each time, you will not be processing from the beginning of the data packet.
Your problem is probably being caused by the nagle algorithm, prevent small amounts of data being sent to reduce congestion. You could try disabling it by setting the following properties on your tcpClient
tcpClient.NoDelay = true;
tcpClient.Client.NoDelay = true
I have created TCP Client application and wanted to read and write to TCP server through my code. For reading from TCP Server I have created thread but it is not continuously firing the code of reading When I send the text from TCP server twice at the second time it gets fired and I am getting the data at the second time. Below is my code of reading and writing the data Please help me to resolve this
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
namespace TCPClient
{
public partial class Form1 : Form
{
int i;
StreamWriter streamWriter;
StreamReader streamReader;
TcpClient client; // Creates a TCP Client
NetworkStream stream; //Creats a NetworkStream (used for sending and receiving data)
byte[] datalength = new byte[256]; // creates a new byte with length 4 ( used for receivng data's lenght)
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
client = new TcpClient("127.0.0.1", 747); //Trys to Connect
ClientReceive(); //Starts Receiving When Connected
// timer1.Enabled = true;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message); // Error handler :D
}
}
public void ClientReceive()
{
stream = client.GetStream(); //Gets The Stream of The Connection
new Thread(() => // Thread (like Timer)
{
//MessageBox.Show(stream.Read(datalength, 0, 256).ToString());
while ((i = stream.Read(datalength, 0, 256)) != 0)//Keeps Trying to Receive the Size of the Message or Data
{
// how to make a byte E.X byte[] examlpe = new byte[the size of the byte here] , i used BitConverter.ToInt32(datalength,0) cuz i received the length of the data in byte called datalength :D
// byte[] data = BitConverter.GetBytes(1000); // Creates a Byte for the data to be Received On
byte[] data = new byte[1000];
stream.Read(data, 0, data.Length); //Receives The Real Data not the Size
this.Invoke((MethodInvoker)delegate // To Write the Received data
{
txtLog.Text += System.Environment.NewLine + "Server : " + Encoding.Default.GetString(data); // Encoding.Default.GetString(data); Converts Bytes Received to String
});
}
}).Start(); // Start the Thread
}
public void ClientSend(string msg)
{
stream = client.GetStream(); //Gets The Stream of The Connection
byte[] data; // creates a new byte without mentioning the size of it cuz its a byte used for sending
data = Encoding.Default.GetBytes(msg); // put the msg in the byte ( it automaticly uses the size of the msg )
int length = data.Length; // Gets the length of the byte data
byte[] datalength = new byte[4]; // Creates a new byte with length of 4
datalength = BitConverter.GetBytes(length); //put the length in a byte to send it
stream.Write(datalength, 0, 4); // sends the data's length
stream.Write(data, 0, data.Length); //Sends the real data
}
private void btnSend_Click(object sender, EventArgs e)
{
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
if (client.Connected) // if the client is connected
{
ClientSend(textBox1.Text); // uses the Function ClientSend and the msg as txtSend.Text
}
}
}
}
I have set up a C# server which at present serves up one test mp3 file over TCP. The code to send the file is as follows
public void RunStreamer()
{
log.MakeLog("Starting streamer");
Run = true;
//Need to look into how to thread this to not block the main window
TcpListener listen = new TcpListener(localAddr, _port);
listen.Start(); //startlistening to client requests
//blocks until a client request comes in
for (; ; )
{
Socket socket = listen.AcceptSocket();
if (socket.Connected)
{
SendFileToClient(socket);
socket.Disconnect(false);
}
}
}
void SendFileToClient(Socket socket)
{
log.MakeLog("Connection made");
NetworkStream netStream = new NetworkStream(socket);
StreamWriter writer = new StreamWriter(netStream);
//Todo - set specfified file - this file just for test
FileStream filestream = File.Open(#"C:\MusicTest\Test.mp3", FileMode.Open, FileAccess.Read, FileShare.Read);
filestream.CopyTo(netStream);
netStream.Flush();
netStream.Close();
}
In my test android set up I am making a call to the server on a button click:
public void btngo_click(View v)
{
final TcpClient client = new TcpClient();
new Thread(new Runnable(){
#Override
public void run() {
final MediaPlayer mediaPlayer = new MediaPlayer();
client.GetStream();
runOnUiThread(new Runnable(){
public void run()
{
int length = client.GetLength();
if(length > 0)
{
byte[] result = client.GetResult();
try {
// create temp file that will hold byte array
File tempMp3 = File.createTempFile("test", "mp3", getCacheDir());
tempMp3.deleteOnExit();
FileOutputStream fos = new FileOutputStream(tempMp3);
fos.write(result);
fos.close();
mediaPlayer.reset();
FileInputStream fis = new FileInputStream(tempMp3);
mediaPlayer.setDataSource(fis.getFD());
mediaPlayer.prepare();
mediaPlayer.start();
} catch (IOException ex) {
String s = ex.toString();
ex.printStackTrace();
}
}
}
});
}
}).start();
}
the stream is received in the TcpClient class which is as follows:
public class TcpClient {
public final static String SERVER_ADDRESS = "127.0.0.1";
public final static int SERVER_PORT = 65000;
public String TotalResult;
public int Length;
byte[] result = new byte[21000000];
public TcpClient()
{
}
public int GetLength()
{
return Length;
}
public byte[] GetResult()
{
return result;
}
public void GetStream()
{
try
{
final Socket socket = new Socket("192.0.0.5", 85000);
final InputStream input = new BufferedInputStream(socket.getInputStream());
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nread;
while((nread = input.read(result, 0, result.length)) != -1)
{
buffer.write(result, 0, nread);
}
buffer.flush();
//input.read(result);
Length = result.length;
input.close();
socket.close();
} catch (UnknownHostException e) {
String exc = e.getMessage();
e.printStackTrace();
} catch (IOException e) {
String exc2 = e.getMessage();
e.printStackTrace();
}
}
}
With apologies for all the code here is my problem.
I am receiving the stream. The temp MP3 file is created and the media player starts. I then only get a short snippet of the test MP3 file (which is a full song). It also jumps about a bit. The length is not the same and the section of the song played is different each time.
How do I receive the full file in a ordered way such that it will provide full play back of the song.
I have tried to route around for this and have an idea that I need to tell my client what file size it should suspect and then perform some loop until all data is received although I have no idea how to successfully implement this if that is the correct solution.
Any pointers on where I am going wrong or what I can do to rectify would be greatly appreciated!!
Having received no answers on this I dug around a bit more. Two things were wrong:
Firstly I had not included the size of the stream as a int sized header in my stream. I understand that for smaller files this will not be a problem but as file sizes grow it is necessary to make sure that the whole stream has been received.
This in turn raised another issue. The int I was sending as byte[] form c# was not returning the correct value in Java. Turns out Java uses sbytes -128 to 127 range as opposed to byte. This then involved a bit of code to convert to an int. then I could instruct the reader to readfully passing in the byte[] buffer with the actual size of the expected stream = voila it worked. MP3 files is received and plays just fine.
I have problem with sending objects via TCPClient. At first, I serialize them into byte array and then I send them. TCPListener recieves some data, but deserializer is throwing exception "Unexpected end of stream".
Here is reciever code:
public void start()
{
TcpListener listener = new TcpListener(IPAddress.Any, 8090);
listener.Start();
while (true)
{
TcpClient client = listener.AcceptTcpClient();
processClient(client);
}
}
public void processClient(TcpClient client)
{
NetworkStream net = client.GetStream();
ReadData(net);
byte[] response = Encoding.UTF8.GetBytes("Hello from the server.");
net.Write(response, 0, response.Length);
net.Close();
client.Close();
}
void ReadData(NetworkStream netstream)
{
byte[] buffer = new byte[2048];
System.IO.MemoryStream memStream = new System.IO.MemoryStream();
netstream.ReadTimeout = 5000;
int bytes = -1;
while ((bytes = netstream.ReadByte()) != -1)
{
memStream.WriteByte((byte)bytes);
}
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bform = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
Packet packet = (Packet)bform.Deserialize(memStream);
OnMessageArrived(this, new MessageEventArgs(packet.From.ToString(), packet.Data.ToString()));
memStream.Close();
netstream.Close();
}
And here is sender code:
public void sendData(string to, Packet data)
{
TcpClient client = new TcpClient();
MemoryStream mstream = new MemoryStream();
client.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8090));
if (client.Connected)
{
NetworkStream stream = client.GetStream();
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bform = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
bform.Serialize(mstream, data);
byte[] buffer = new byte[2048];
mstream.Read(buffer, 0, buffer.Length);
stream.Write(buffer, 0, buffer.Length);
stream.Flush();
stream.Close();
client.Close();
}
}
Sender main method:
static void Main(string[] args)
{
SimplestTCPIP.Client client = new SimplestTCPIP.Client();
Packet packet = new Packet("client", "server", IPAddress.Parse("127.0.0.1"));
client.sendData("server", packet);
Console.WriteLine("IP: " + GetIP().ToString());
Console.Read();
}
Reciever main method:
static void Main(string[] args)
{
SimplestTCPIP.Server server = new SimplestTCPIP.Server();
server.OnMessageArrived += new SimplestTCPIP.Server.MessageArrived(server_OnMessageArrived);
Thread thread = new Thread(server.start);
thread.Start();
}
static void server_OnMessageArrived(object sender, SimplestTCPIP.Server.MessageEventArgs m)
{
Console.WriteLine(m.From + " : " + m.Text);
}
In your sendData method you serialize the object to a memory stream and then read it back into a buffer of 2048 bytes before writing it to the network stream. If the serialzed object is > 2048 bytes you would have a problem. I would try just serializing directly to the network stream or at least using the same kind of code as in your ReadData method where you write byte by byte.
Edit:
The size of the data is probably not the problem. You should still avoid the hard coded buffer size and stick with the code change you mention in the comment. Given your comment the problem lies elsewhere.
In both your sender and your receiver you write to a memory stream and then read from it. You can't do that unless you set the current position in the stream back to zero between the write and read.
So in your sendData method on the client add the line
mstream.Seek(0, SeekOrigin.Begin);
right after
bform.Serialize(mstream, data);
And in the ReadData method of your server add the line
memStream.Seek(0, SeekOrigin.Begin);
right before
Packet packet = (Packet)bform.Deserialize(memStream);
That way the memory stream is set to the beginning before you try and read from it.
I think you could just skip the memory stream all together and just read and write to the network stream, but you might have other reasons for it.