I have a small server that is received and sends the message back to the client.
this is the client-side
when I open the client it will connect to server through Connect()
public Form1()
{
InitializeComponent();
Connect();
CheckForIllegalCrossThreadCalls = false;
}
this is my connect
void Connect()
{
ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9999);
server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
server.Connect(ipep);
}
catch (SocketException e)
{
MessageBox.Show(Convert.ToString(e));
}
Thread listen = new Thread(Receive);
listen.IsBackground = true; ;
listen.Start();
}
and I have a receive like this
void Receive()
{
datarec = new byte[1024];
try
{
while (true)
{
string StringData;
rec = server.Receive(datarec);
StringData = Encoding.ASCII.GetString(data, 0, rec);
txtShow.Text = StringData;
}
}
catch
{
Close();
}
}
and I send data through a button have Send method
void Send(string s)
{
data = new byte[1024];
data = Encoding.ASCII.GetBytes(s);
server.Send(data, data.Length, SocketFlags.None);
}
Send button
private void button1_Click(object sender, EventArgs e)
{
string s = txtText.Text;
Send(s);
}
this is the server-side
I have a thread server
public static void Process(Socket client)
{
byte[] data = new byte[1024];
int recv;
string dataInput;
IPEndPoint clientep = (IPEndPoint)client.RemoteEndPoint;
Console.WriteLine("Connected with {0} at port {1}", clientep.Address, clientep.Port);
while (true)
{
try
{
recv = client.Receive(data);
dataInput = Encoding.ASCII.GetString(data, 0, recv);
Console.WriteLine(dataInput);
client.Send(data);
}
catch (SocketException e)
{
Console.WriteLine(e);
}
}
}
this is the server main
public static void Main()
{
byte[] rec = new byte[1024];
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9999);
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(ipep);
server.Listen(10);
Console.WriteLine("Waiting for client...");
Console.WriteLine("LOG CHAT");
while (true)
{
Socket client = server.Accept();
Core core = new Core();
Thread t = new Thread(() => Core.Process(client));
t.Start();
}
}
the server receive message but when it sends a message back it has an error "An established connection was aborted by the software in your host machine"
Can you guys tell me where I was wrong and how can I fix it?
When you call client.Send(data) in your server code, you will send the whole 1024 byte buffer back to the client, not just the data received.
Encoding.ASCII.GetString in the client could fail when processing this garbage and the exception will close the connection.
Try to replace client.Send(data) by client.Send(data, recv, SocketFlags.None).
Also, you should not update UI controls directly from a background thread, Use Control.Invoke for this. Failing to do so will also throw an exception and close the connection.
Related
I'm creating an async TCP Server that works kinda like a chat room, or at least it should. When a new client connects to the server he receives a welcome message and also everytime he sends a message, the server echos it back. It works well when only one client is connected, but when another one connects, he doesn't receive the welcome msg nor the echos.
Here's some of my code.
private void btn_startserver_Click(object sender, EventArgs e)
{
server = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp); //Populates the Server obj.
IPEndPoint iep = new IPEndPoint(IPAddress.Any, 23);
server.Bind(iep);
server.Listen(5);
server.BeginAccept(new AsyncCallback(AcceptConn), server);
WriteOnLog("Waiting for incoming connections...");
Thread t1 = new Thread(() => verifyCon(server));
t1.Start();
}
public void AcceptConn(IAsyncResult iar)
{
Socket oldserver = (Socket)iar.AsyncState;
Socket client = oldserver.EndAccept(iar);
clientList.Add(client);
WriteOnLog("Connected to: " + client.RemoteEndPoint.ToString());
string stringData = "Connected Successfully\r\nWelcome to the Server\r\n";
byte[] message1 = Encoding.UTF8.GetBytes(stringData);
client.BeginSend(message1, 0, message1.Length, SocketFlags.None,
new AsyncCallback(SendData), client);
WriteOnClients(client.RemoteEndPoint.ToString(), "add");
}
void SendData(IAsyncResult iar)
{
Socket client = (Socket)iar.AsyncState;
int sent = client.EndSend(iar);
client.BeginReceive(data, 0, size, SocketFlags.None,
new AsyncCallback(ReceiveData), client);
}
void ReceiveData(IAsyncResult iar)
{
Socket client = (Socket)iar.AsyncState;
string curClient = client.RemoteEndPoint.ToString();
int recv = client.EndReceive(iar);
if (recv == 0)
{
client.Close();
WriteOnLog("Connection lost with " + curClient);
WriteOnClients(curClient, "remove");
WriteOnLog("Waiting for client...");
connectedClients.Remove(curClient);
server.BeginAccept(new AsyncCallback(AcceptConn), server);
return;
}
string receivedData = Encoding.ASCII.GetString(data, 0, recv);
WriteOnLog(receivedData);
byte[] message2 = Encoding.UTF8.GetBytes(receivedData);
client.BeginSend(message2, 0, message2.Length, SocketFlags.None,
new AsyncCallback(SendData), client);
}
After you handle the first incoming connection (EndAccept), you need to call BeginAccept again to accept the next connection.
Currently you call BeginAccept only during initialization, and when a client disconnects.
below is roughly how I normally do when trying to setup a connection on my server with my slient device:
IPEndPoint localEP = new IPEndPoint(IPAddress.Any, nConst3rdPartyPort);
the3rdPartyListener = new Socket(localEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
the3rdPartyListener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
the3rdPartyListener.Bind(localEP);
the3rdPartyListener.Listen(100);
the3rdPartyListener.BeginAccept(new AsyncCallback(AcceptConnectBack), the3rdPartyListener);
Any client device can connect to my server if they know the server ip and port number.
Now, I want to do filtering of client device. Only specific client device can connect to my server.
Is it that we can insert a unique ID to client so that the client with only that unique ID can connect to my server?
How do we ensure that the client is the specific client that we want?
This is for security reason to prevent unauthorized client from connecting to the server.
You can use IPEndPoint Address method to retrieve the remote IPAddress and make a whitelist to check who can connect your server.
string clientIP = ((IPEndPoint)(the3rdPartyListener.RemoteEndPoint)).Address.ToString();
------------------------------------------------------------------------------------------------------------------------------------
Updated:
I'm not sure Csharp Socket has verified device method or not. But I have a method on below.
Use NetworkStream to pass data from Client to Server that verified the client.
Server Side:
TcpClient client;
TcpListener server;
Thread thread;
Thread threadTwo;
byte[] datalength = new byte[4];
public Server()
{
InitializeComponent();
server = new TcpListener(IPAddress.Any, 2018);
server.Start();
thread = new Thread(() =>
{
client = server.AcceptTcpClient();
ServerReceive();
}
thread.Start();
}
void ServerReceive()
{
networkStream = client.GetStream();
threadTwo = new Thread(() =>
{
while ((i = networkStream.Read(datalength, 0, 4)) != 0)
{
byte[] data = new byte[BitConverter.ToInt32(datalength, 0)];
networkStream.Read(data, 0, data.Length);
this.Invoke((MethodInvoker)delegate
{
if(Encoding.Default.GetString(data) == "unique ID")
{
//Do your job
}
}
}
}
threadTwo.Start();
}
Client Side:
NetworkStream networkStream;
TcpClient client;
byte[] datalength = new byte[4];
public Client()
{
InitializeComponent();
try
{
client = new TcpClient("your server ip", 2018);
ClientSend("unique ID");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
void ClientSend(string msg)
{
try
{
networkStream = client.GetStream();
byte[] data;
data = Encoding.Default.GetBytes(msg);
int length = data.Length;
byte[] datalength = new byte[4];
datalength = BitConverter.GetBytes(length);
networkStream.Write(datalength, 0, 4);
networkStream.Write(data, 0, data.Length);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
I have a basic C#.NET UDP server and client code and I am trying to port it to UWP. For UWP, I experimented with DatagramSocket and regular Socket class. I am seeing almost 40% packet drops on incoming UDP packets on UWP Server using DatagramSocket class. If I use UWP Sockets, I see the packet loss of around 70%. The old .NET code shows 0% packet loss.
I am thinking maybe I am not using the UWP APIs correctly and hence I am getting poor performance. Could someone guide me on how to improve UWP server performance?
Right now, all the tests are done using loop-back. UWP doesn't allow loop-back by default so I am followed the instructions mentioned here to enable loop-back.
The server listens for packet on 50000 port and Client code sends packets of around 60 bytes to server from 50001.
The C#.NET client code is below:
try
{
byte[] buffer = new byte[1024];
IPEndPoint localEP = new IPEndPoint(IPAddress.Any, 50001);
IPAddress remoteIp = System.Net.IPAddress.Parse("127.0.0.1");
IPEndPoint remoteEP = new IPEndPoint(remoteIp, 50000);
Socket sender = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
try
{
sender.Bind(localEP);
for(int i = 0; i < 10000; i++)
{
//Thread.Sleep(1);
// Encode the data string into a byte array.
string ClientReq = "Client Request:: " + i.ToString() + " "+ Guid.NewGuid().ToString();
byte[] msg = Encoding.ASCII.GetBytes(ClientReq);
// Send the data through the socket.
int sentBytes = sender.SendTo(msg, remoteEP);
Console.WriteLine("{0}::{1} Client Request ({2} bytes):: {3}.",
remoteEP.Address.ToString(),
remoteEP.Port.ToString(),
sentBytes,
ClientReq
);
}
// Release the socket.
sender.Close();
//Console.ReadKey();
}
catch(ArgumentNullException ane)
{
Console.WriteLine("ArgumentNullException : {0}", ane.ToString());
}
catch(SocketException se)
{
Console.WriteLine("SocketException : {0}", se.ToString());
}
catch(Exception e)
{
Console.WriteLine("Unexpected exception : {0}", e.ToString());
}
}
catch(Exception e)
{
Console.WriteLine(e.ToString());
}
C#.NET Server Code:
byte[] buffer = new Byte[1024];
IPAddress LocalIp = IPAddress.Any; //System.Net.IPAddress.Parse("127.0.0.1");
IPEndPoint localEndPoint = new IPEndPoint(LocalIp, 50000);
// Create a UDP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp );
// Bind the socket to the local endpoint and
// listen for incoming connections.
try
{
listener.Bind(localEndPoint);
Console.WriteLine("Bind Complete");
int messagesReceived = 0;
while(true)
{
EndPoint receiveEP = new IPEndPoint(IPAddress.Any, 0);
int receivedBytes = listener.ReceiveFrom(buffer, ref receiveEP);
messagesReceived++;
IPEndPoint receiveIPEP = receiveEP as IPEndPoint;
Console.WriteLine("{0}::{1}::{2} Client Request ({3} bytes):: {4}.",
messagesReceived,
receiveIPEP.Address.ToString(),
receiveIPEP.Port.ToString(),
receivedBytes,
System.Text.Encoding.UTF8.GetString(buffer, 0, receivedBytes));
}
}
catch(Exception e)
{
Console.WriteLine(e.ToString());
}
With this above code, i see all the 10000 packets are received at server.
UWP DatagramSocket Code:
DgSocket = new DatagramSocket();
DgSocket.MessageReceived += SocketListener_MessageReceived;
await DgSocket.BindServiceNameAsync("50000");
private async void SocketListener_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
uint datalen = args.GetDataReader().UnconsumedBufferLength;
DataReader reader = args.GetDataReader();
byte[] dataBuffer = new byte[reader.UnconsumedBufferLength];
reader.ReadBytes(dataBuffer);
await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
lock(_lockObject)
{
DgPackets++;
DgPacketList.Add(Encoding.ASCII.GetString(dataBuffer));
}
});
}
UWP Socket Code:
public void SetupSimpleSocketListener()
{
try
{
IPAddress LocalIp = IPAddress.Any;
IPEndPoint localEndPoint = new IPEndPoint(LocalIp, 50000);
SimpleSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp );
byte[] buffer = new Byte[1024];
SimpleSocket.Bind(localEndPoint);
Debug.WriteLine("Bind Complete");
SocketAsyncEventArgs sockarg = new SocketAsyncEventArgs();
sockarg.Completed += Sockarg_Completed;
sockarg.RemoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
sockarg.SetBuffer(buffer, 0, buffer.Length);
if(!SimpleSocket.ReceiveFromAsync(sockarg))
{
Sockarg_Completed(this, sockarg);
}
}
catch(Exception e)
{
Debug.WriteLine(e.ToString());
}
}
private async void Sockarg_Completed(object sender, SocketAsyncEventArgs e)
{
await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
lock(_lockObject)
{
SimpleSocketPackets++;
SimpleSocketPacketList.Add(Encoding.ASCII.GetString(e.Buffer, 0, e.BytesTransferred));
}
});
if(e.SocketError == System.Net.Sockets.SocketError.Success)
{
if(!SimpleSocket.ReceiveFromAsync(e))
{
Sockarg_Completed(this, e);
}
}
}
I have posted the full source code on github:
The form from this code does not appear. How can I get it to show? Through the console, everything works.
void Form1_Load(object sender, EventArgs e)
{
String host = Dns.GetHostName();//name kompa
//ip pc
IPAddress ip = Dns.GetHostByName(host).AddressList[0];
const int port = 2222;
label1.Text = host;
label2.Text = "Сервер запущен на " + ip.ToString() + ":" + port.ToString();
server.serversocket = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
server.serversocket.Bind(new IPEndPoint(ip, port));
server.serversocket.Listen(100);
//ошибочка в цикле
while (server.work)
{
MessageBox.Show("dsff");
Socket handle = server.serversocket.Accept();
richTextBox1.AppendText("новое подключение" + handle.RemoteEndPoint.ToString());
new user(handle);
}
As Hans Passant said, you are blocking the GUI thread with a while loop. That will just not do. Events must return asap and can never run indefinitely. And this Form_Load can not return until the server stops working.
It is very common mistake and basically the reason we all went crazy for multitasking and multithreading this century. You can't even do a word processor without it anymore.
You are blocking the ui thread. Using a separate thread for the synchronous socket server would be a solution. The other option would be to use an asynchronous socket so that the execution of the application is not blocked while it waits for a connection. Based on the socket code samples.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
InitSocketServer();
}
internal void InitSocketServer()
{
IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
var ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);
try
{
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(localEndPoint);
listener.Listen(100);
listener.BeginAccept(AcceptCallback, listener);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void AcceptCallback(IAsyncResult ar)
{
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
string data = null;
while (true)
{
var bytes = new byte[1024];
int bytesRec = handler.Receive(bytes);
data += Encoding.ASCII.GetString(bytes, 0, bytesRec);
if (data.IndexOf("<EOF>") > -1)
{
break;
}
}
MessageBox.Show(handler.RemoteEndPoint + " : " + data);
byte[] msg = Encoding.ASCII.GetBytes(data);
handler.Send(msg);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Test button click");
}
}
i've got the following problem in a client socket (sync) / server socket (async) environment.
If I send multiple messages from the client to the server, the first one finishs without any problems and will be received by the client without issues. When I send the 2nd message, just a few bytes go through. It doesn't seem to be a client problem, because it looks the client sends the whole message all the time. The crazy thing is, if I completely stop the project on the client and start again the first message completes again, also if the server component runs through all the time.
What I want to do...
Basically, I want to transfer different objects, most xml structured through the network and receive it on the client. Therefore, I do the Serialization/Deserialization.
The basics of the following code are extended msdn examples.
//CLIENT:
class ProgramClient
{
static void Main(string[] args)
{
string rootNode = "config";
StreamReader configStream = new StreamReader(config);
XmlDocument xml = new XmlDocument();
xml.Load(configStream);
SynchronousSocketClient socket = new SynchronousSocketClient("192.168.0.1", 40001, "c:\\log", xml);
socket.StartClient();
socket.Dispose();
socket = new SynchronousSocketClient("192.168.0.1", 40001, "c:\\log", xml);
socket.StartClient();
socket.Dispose();
}
}
class SynchronousSocketClient : IDisposable
{
private string ip;
private int port;
private object data;
public StreamWriter log;
public event EventHandler Disposed;
public SynchronousSocketClient(string ip, int port, string logfile, object data)
{
this.ip = ip;
this.port = port;
this.data = data;
openLog(logfile);
}
public void openLog(string logfile)
{
log = new StreamWriter(logfile, true);
}
public void Dispose()
{
log.Close();
if (this.Disposed != null)
this.Disposed(this, EventArgs.Empty);
}
// Convert an object to a byte array
private byte[] Serialize(object obj)
{
Stream stream = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(stream, obj);
byte[] b = null;
b = new byte[stream.Length];
stream.Position = 0;
stream.Read(b, 0, (int)stream.Length);
stream.Close();
return b;
}
public void StartClient()
{
// Data buffer for incoming data.
byte[] bytes = new byte[1024];
// Connect to a remote device.
try {
// Establish the remote endpoint for the socket.
// This example uses port 11000 on the local computer.
IPHostEntry ipHostInfo = Dns.GetHostEntry(ip);
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint remoteEP = new IPEndPoint(ipAddress,port);
// Create a TCP/IP socket.
Socket sender = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp );
// Connect the socket to the remote endpoint. Catch any errors.
try {
sender.Connect(remoteEP);
log.WriteLine(DateTime.Now+": Socket connected to {0}",
sender.RemoteEndPoint.ToString());
// Encode the data string into a byte array.
byte[] msg = Serialize(data);
// Send the data through the socket.
int bytesSent = sender.Send(msg);
// Receive the response from the remote device.
int bytesRec = sender.Receive(bytes);
log.WriteLine(DateTime.Now + ": {0}",
Encoding.Unicode.GetString(bytes,0,bytesRec));
// Release the socket.
sender.Shutdown(SocketShutdown.Both);
sender.Close();
} catch (ArgumentNullException ane) {
log.WriteLine(DateTime.Now + ": ArgumentNullException : {0}", ane.ToString());
} catch (SocketException se) {
log.WriteLine(DateTime.Now + ": SocketException : {0}", se.ToString());
} catch (Exception e) {
log.WriteLine(DateTime.Now + ": Unexpected exception : {0}", e.ToString());
}
} catch (Exception e) {
log.WriteLine(DateTime.Now+": "+e.ToString());
}
}
}
//SERVER:
class ProgramServer
{
static void Main(string[] args)
{
NetworkSocket socket = new NetworkSocket(nwsocketport);
socket.Start();
}
}
public class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of send buffer.
public const int sBufferSize = 1024;
// send buffer.
public byte[] sBuffer = new byte[sBufferSize];
// Received data object;
public object data = null;
// bytes read so far
public int bytesRead;
//receive buffer
public byte[] rBuffer;
}
public class NetworkSocket
{
private int port;
Socket listener;
IPEndPoint localEndPoint;
public NetworkSocket(int port) {
this.port = port;
}
public void Start() {
// Establish the local endpoint for the socket.
IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[1];
localEndPoint = new IPEndPoint(ipAddress, port);
// Create a TCP/IP socket.
listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp );
//set socket timeouts
listener.SendTimeout = 5000;
listener.ReceiveTimeout = 5000;
// Bind the socket to the local endpoint and listen for incoming connections.
try {
listener.Bind(localEndPoint);
listener.Listen(1);
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
public void AcceptCallback(IAsyncResult ar) {
// Signal the main thread to continue.
//allDone.Set();
// Get the socket that handles the client request.
Socket listener = (Socket) ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// Create the state object.
StateObject state = new StateObject();
// Data buffer for incoming data.
state.rBuffer = new Byte[listener.ReceiveBufferSize];
state.workSocket = handler;
handler.BeginReceive(state.rBuffer, 0, state.rBuffer.Length, 0,
new AsyncCallback(ReadCallback), state);
try
{
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public void ReadCallback(IAsyncResult ar) {
// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject state = (StateObject) ar.AsyncState;
Socket handler = state.workSocket;
//handler.ReceiveTimeout = 2000;
// Read data from the client socket.
state.bytesRead = handler.EndReceive(ar);
Send(handler, "paket successfully tranferred");
state.data = Deserialize(state.rBuffer);
bool xmlDoc = true;
try
{
XDocument.Parse(state.data.ToString());
}
catch
{
xmlDoc = false;
}
if (xmlDoc)
XMLHandler.update(state.data.ToString());
}
private void Send(Socket handler, String data) {
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.Unicode.GetBytes(data);
// Begin sending the data to the remote device.
handler.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), handler);
}
private void SendCallback(IAsyncResult ar) {
try {
// Retrieve the socket from the state object.
Socket handler = (Socket) ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = handler.EndSend(ar);
Console.WriteLine("Sent {0} bytes to client.", bytesSent);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
// Convert a byte array to an Object
private object Deserialize(byte[] b)
{
MemoryStream stream = new MemoryStream(b);
BinaryFormatter bf = new BinaryFormatter();
object obj = bf.Deserialize(stream);
stream.Close();
return obj;
}
// convert object to byte array
private byte[] Serialize(object obj)
{
Stream stream = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(stream, obj);
byte[] b = null;
b = new byte[stream.Length];
stream.Position = 0;
stream.Read(b, 0, (int)stream.Length);
stream.Close();
return b;
}
}
Could anybody please help me with my problem? I am not experienced in Socket Programming...
In your ReadCallback you need to start another BeginReceive, just like how you call BeginAccept in the AcceptCallback method.
A more serious issue with your code is that you expect to receive one entire message per ReadCallback. In reality, you could receive half a message, one byte, or three messages.