NetworkStream.Read() doesn't work and throws ArgumentOutOfRangeException - c#

Just trying to create a chat server-client
This is the server waiting for a client connection (optional)*
TcpListener serverSocket = new TcpListener(8888);
int requestCount = 0;
TcpClient clientSocket = default(TcpClient);
serverSocket.Start();
Console.WriteLine(" >> Server Started");
clientSocket = serverSocket.AcceptTcpClient();
Console.WriteLine(" >> Accept connection from client");
Then, the client connects to the server (optional)*
System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();
clientSocket.Connect("127.0.0.1", 8888);
Then, on the client side, I send the message from a windows form, and the button click event does this:
NetworkStream serverStream = clientSocket.GetStream();
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(textBox2.Text + "$");
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
//this goes to the server ------> to the part (4)
//returning from the server <------
byte[] inStream = new byte[10025];
serverStream.Read(inStream, 0, (int)clientSocket.ReceiveBufferSize);
string returndata = System.Text.Encoding.ASCII.GetString(inStream);
textBox2.Text = "";
textBox2.Focus();
Finally, on the server side, an infinite bucle for client requests. And here is where I got the problem on the networkStream.Read()
while ((true))
{
try
{
requestCount = requestCount + 1;
NetworkStream networkStream = clientSocket.GetStream();
byte[] bytesFrom = new byte[10025];
if (networkStream.DataAvailable)
{
**networkStream.Read(bytesFrom, 0, (int) clientSocket.ReceiveBufferSize);**
string dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
Console.WriteLine(" >> Data from client - " + dataFromClient);
string serverResponse = "Last Message from client" + dataFromClient;
Byte[] sendBytes = Encoding.ASCII.GetBytes(serverResponse);
networkStream.Write(sendBytes, 0, sendBytes.Length);
networkStream.Flush();
Console.WriteLine(" >> " + serverResponse);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
I debugged step by step (on server and client), and it's all fine until I get to the networkStream.Read() method, and throws ArgumentOutOfRangeException... Please, anybody help me or tell me where the error is.
*I say optional because the 1. and 2. steps are fine (at least, I think)

From the MSDN, ArgumentOutOfRangeException means that offset or count is negative(2nd and 3rd parameters), OR the "size(count)" parameter is greater than the length of buffer minus the value of the "offset" parameter.
I'd try passing bytesFrom.Length as opposed to clientSocket.ReceiveBufferSize.

Related

C# winform TCP/IP problem sending string to stream

I am trying to convert an existing C# console app code to a C# winform the code below works well.
class Program
{
const int PORT_NO = 49211;
const string SERVER_IP = "127.0.0.1";
static void Main(string[] args)
{
//---data to send to the server---
string textToSend = DateTime.Now.ToString();
//---create a TCPClient object at the IP and port no.---
TcpClient client = new TcpClient(SERVER_IP, PORT_NO);
NetworkStream nwStream = client.GetStream();
byte[] bytesToSend = ASCIIEncoding.ASCII.GetBytes(textToSend);
//---send the text---
Console.WriteLine("Sending : " + textToSend);
nwStream.Write(bytesToSend, 0, bytesToSend.Length);
//---read back the text---
byte[] bytesToRead = new byte[client.ReceiveBufferSize];
int bytesRead = nwStream.Read(bytesToRead, 0, client.ReceiveBufferSize);
Console.WriteLine("Received : " + Encoding.ASCII.GetString(bytesToRead, 0, bytesRead));
Console.ReadLine();
client.Close();
}
}
But when i tried to convert this into a winform app, the application freeze until i manually stop in on Visual Studio. I Attached it into a button click event.
const int PORT_NO = 49211;
const string SERVER_IP = "127.0.0.1";
private void button1_Click(object sender, EventArgs e)
{
//---data to send to the server---
string textToSend = DateTime.Now.ToString();
//---create a TCPClient object at the IP and port no.---
TcpClient client = new TcpClient(SERVER_IP, PORT_NO);
NetworkStream nwStream = client.GetStream();
byte[] bytesToSend = ASCIIEncoding.ASCII.GetBytes(textToSend);
//---send the text---
lstProgress.Items.Add("Sending : " + textToSend);
nwStream.Write(bytesToSend, 0, bytesToSend.Length);
//---read back the text---
byte[] bytesToRead = new byte[client.ReceiveBufferSize];
int bytesRead = nwStream.Read(bytesToRead, 0, client.ReceiveBufferSize);
lstProgress.Items.Add("Received : " + Encoding.ASCII.GetString(bytesToRead, 0, bytesRead));
client.Close();
}
Any suggestion would be great thanks in advance!

TCPlistener server-client and client-server ( send message to client from server)

All i want to do is send message to client from server. I try a lot of tutorial etc. but still can't send message from server to client.
Send from client to server is simple and have it in code. When client Send "HI" to server i want to respond Hi to client. But dunno what should i add to my code. Can someone help me with that? Please don't do it like duplicate i know there is a lot of similar topic but can't find solution.
Server code:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
IPAddress ip = Dns.GetHostEntry("localhost").AddressList[0];
TcpListener server = new TcpListener(ip, Convert.ToInt32(8555));
TcpClient client = default(TcpClient);
try
{
server.Start();
Console.WriteLine("Server started...");
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
};
while (true)
{
client = server.AcceptTcpClient();
byte[] receivetBuffer = new byte[100];
NetworkStream stream = client.GetStream();
stream.Read(receivetBuffer, 0, receivetBuffer.Length);
StringBuilder msg = new StringBuilder();
foreach(byte b in receivetBuffer)
{
if (b.Equals(59))
{
break;
}
else
{
msg.Append(Convert.ToChar(b).ToString());
}
}
////Resive message :
if (msg.ToString() =="HI")
{
///#EDIT 1
///// HERE Is SENDING MESSAGE TO CLIENT//////////
int byteCount = Encoding.ASCII.GetByteCount("You said HI" + 1);
byte[] sendData = new byte[byteCount];
sendData = Encoding.ASCII.GetBytes("You said HI" + ";");
stream.Write(sendData, 0, sendData.Length);
}
}
Client code:
private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
{
try
{
string serverIP = "localhost";
int port = Convert.ToInt32(8555);
TcpClient client = new TcpClient(serverIP, port);
int byteCount = Encoding.ASCII.GetByteCount("HI"+ 1);
byte[] sendData = new byte[byteCount];
sendData = Encoding.ASCII.GetBytes("HI" + ";");
NetworkStream stream = client.GetStream();
stream.Write(sendData, 0, sendData.Length);
///////////////////////////////HERE I WANT A read message from server/
/////////////////////////////////////////////////////////////////////
stream.Close();
client.Close();
}
catch(Exception ex)
{
ex.ToString();
}
}
Try this Here is my version of client and server ,feel free to ask if any reference problem ,the client wait for server to (online) then if server is online connect with it.
Method to Connect with Server
private void Connectwithserver(ref TcpClient client)
{
try
{
//this is server ip and server listen port
server = new TcpClient("192.168.100.7", 8080);
}
catch (SocketException ex)
{
//exceptionsobj.WriteException(ex);
Thread.Sleep(TimeSpan.FromSeconds(10));
RunBoTClient();
}
}
byte[] data = new byte[1024];
string stringData;
TcpClient client;
private void RunClient()
{
NetworkStream ns;
Connectwithserver(ref client);
while (true)
{
ns = client.GetStream();
//old
// ns.ReadTimeout = 50000;
//old
ns.ReadTimeout = 50000;
ns.WriteTimeout = 50000;
int recv = default(int);
try
{
recv = ns.Read(data, 0, data.Length);
}
catch (Exception ex)
{
//exceptionsobj.WriteException(ex);
Thread.Sleep(TimeSpan.FromSeconds(10));
//try to reconnect if server not respond
RunClient();
}
//READ SERVER RESPONSE/MESSAGE
stringData = Encoding.ASCII.GetString(data, 0, recv);
}
}
Server
IPAddress localAdd = IPAddress.Parse(SERVER_IP);
TcpListener listener = new TcpListener(localAdd, PORT_NO);
Console.WriteLine("Listening...");
listener.Start();
while (true)
{
//---incoming client connected---
TcpClient client = listener.AcceptTcpClient();
//---get the incoming data through a network stream---
NetworkStream nwStream = client.GetStream();
byte[] buffer = new byte[client.ReceiveBufferSize];
//---read incoming stream---
int bytesRead = nwStream.Read(buffer, 0, client.ReceiveBufferSize);
//---convert the data received into a string---
string dataReceived = Encoding.ASCII.GetString(buffer, 0, bytesRead);
Console.WriteLine("Received : " + dataReceived);
//IF YOU WANT TO WRITE BACK TO CLIENT USE
string yourmessage = console.ReadLine();
Byte[] sendBytes = Encoding.ASCII.GetBytes(yourmessage);
//---write back the text to the client---
Console.WriteLine("Sending back : " + yourmessage );
nwStream.Write(sendBytes, 0, sendBytes.Length);
client.Close();
}
listener.Stop();

Exception in opening a socket at my IP address

I am new in socket programming C#. I am trying to make a chat server between two computers but I am unable to do that because I cant start my Socket..... I gave the Server Program my IP address but gives me an exception... "The requested address is not valid in its context" ...Here is the code:
IPAddress hostIPAddress = IPAddress.Parse("178.189.27.85");
TcpListener serverSocket = new TcpListener(hostIPAddress, 8888);
int requestCount = 0;
TcpClient clientSocket = default(TcpClient);
serverSocket.Start();
Console.WriteLine(" >> Server Started");
clientSocket = serverSocket.AcceptTcpClient();
Console.WriteLine(" >> Accept connection from client");
requestCount = 0;
while ((true))
{
try
{
requestCount = requestCount + 1;
NetworkStream networkStream = clientSocket.GetStream();
byte[] bytesFrom = new byte[10025];
networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);
string dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
Console.WriteLine(" >> Data from client - " + dataFromClient);
string serverResponse = "Last Message from client" + dataFromClient;
Byte[] sendBytes = Encoding.ASCII.GetBytes(serverResponse);
networkStream.Write(sendBytes, 0, sendBytes.Length);
networkStream.Flush();
Console.WriteLine(" >> " + serverResponse);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
clientSocket.Close();
serverSocket.Stop();
Console.WriteLine(" >> exit");
Console.ReadLine();
Client program
try {
TcpClient tcpclnt = new TcpClient();
Console.WriteLine("Connecting.....");
tcpclnt.Connect("192.168.128.1",8888);
// 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);
}
IPAddress hostIPAddress = IPAddress.Parse("178.189.27.85");
Is your computer actually on the public internet? I would expect your computer to have a private IP (eg 192.168.x.y, 172.16-32.x.y, 10.x.y.z) unless it is directly connected to your internet connection.
Assuming you're on Windows, use a Command Prompt and run ipconfig, or visit Control Panel and look for your network settings. On Windows 7 for instance it's in the Network and Sharing Center, under "Change adapter settings"; look for the active adapter, right click and choose "Status".
Once you find your local IP address, use that. Or you can use 0.0.0.0 as a wildcard address – in effect saying "Just accept connections from wherever, I don't care what my IP address is."

Socket communication output issue

In getting used to Sockets using Client server communication here is my code.
//server partl
try
{
IPAddress ipAd = IPAddress.Parse("127.0.0.1"); //use local m/c IP address, and use the same in the client
/* Initializes the Listener */
TcpListener myList = new TcpListener(ipAd, 8020);
/* Start Listeneting at the specified port */
myList.Start();
Socket s = myList.AcceptSocket();
Console.WriteLine("Connection accepted from " + s.RemoteEndPoint);
byte[] b = new byte[100];
int k = s.Receive(b);
//Console.WriteLine("Recieved...");
//Writes to label1
for (int i = 0; i < k; i++)
label1.Text = b[i].ToString();
//ASCII endoing to use ACK.
ASCIIEncoding asen = new ASCIIEncoding();
s.Send(asen.GetBytes("The string was recieved by the server."));
Console.WriteLine("\nSent Acknowledgement");
/* clean up */
s.Close();
myList.Stop();
}
catch (Exception ex)
{
Console.WriteLine("Error..... " + ex.StackTrace);
}
//Client part
try
{
TcpClient tcpclnt = new TcpClient();
Console.WriteLine("Connecting.....");
tcpclnt.Connect("127.0.0.1", 8020); // use the ipaddress as in the server program
Console.WriteLine("Connected");
Console.Write("Enter the string to be transmitted : ");
//gets the text from textbox
String str = textBox1.Text;
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 ex)
{
Console.WriteLine("Error..... " + ex.StackTrace);
}
}
I am using a form to communicate on local host and writing a one .cs file and want to show the text(from textbox) from Client-labelled portion to the label on server-labelled portion.
Any idea why its not showing output?. New to sockets !!!
When socket receives the data instead of loop simply use this:
if (k > 0)
label1.Text = Encoding.UTF8.GetString(b);
Also you can use this for simply send and receive data using TcpClient which is a wrapper around socket.

Async StreamWriter read and write C#

I've been coding a chat program that is made of two parts: server and client. The server uses TcpListener to listen for incoming requests to join the server, and the client uses TcpClient that it uses to connect to the server, and send messages. So far I have the handshake that is the first message sent when the client connects - it contains the client's IP address and the nickname set. I don't know how to make the server to listen asynchronously, because if it's not async, then the chat will be client -> server -> client -> server whereas it needs to be connected to multiple clients at once, and receive multiple messages at once. My code so far is written synchronously:
Client:
public void StartClient(string serverIP)
{
ReadWrite rw = new ReadWrite();
string nick = rw.GetNick();
string handshakeContents = "HANDSHAKE:" + nick + ":" + GetIP();
Int32 serverPort = 1336; // yay
TcpClient client = new TcpClient(serverIP, serverPort);
Console.WriteLine("Sending initial handshake: {0}", handshakeContents);
Byte[] data = System.Text.Encoding.ASCII.GetBytes(handshakeContents); // Convert handshakeContents to Byte[]
NetworkStream stream = client.GetStream(); // Instantiate object "stream" for use in read/write
stream.Write(data, 0, data.Length); // Send handshakeContents in Byte[] to server
Console.WriteLine(" - Connecting to IlanChat Server on ip {0}", serverIP);
Thread.Sleep(1000); // sleep 1s
data = new Byte[256];
string responseHandshake = String.Empty; // response handshake from server
Int32 bytes = stream.Read(data, 0, data.Length); // Read handshake.
responseHandshake = System.Text.Encoding.ASCII.GetString(data, 0, bytes); // Decode from Byte[] to ASCII string
Console.WriteLine(" - Received response handshake: {0}", responseHandshake);
Console.WriteLine(" - Successfully connected to IlanChat server on IP {0}", serverIP); // display message
Thread.Sleep(2000);
Console.Clear();
List<string> messagesRecieved = new List<string>();
while(true)
{
Console.Clear();
foreach (string msg in messagesRecieved)
{
Console.WriteLine(msg);
}
Console.WriteLine();
Console.Write("Enter message: ");
string msgRaw = Console.ReadLine();
string sendMsg = nick + ": " + msgRaw;
data = new Byte[256];
data = System.Text.Encoding.ASCII.GetBytes(sendMsg);
stream.Write(data, 0, data.Length); // finish this async shit
}
}
Server:
List<string> clientIP = new List<string>();
List<string> clientNicks = new List<string>();
string responseHandshake = "hello";
Int32 serverPort = 1336;
IPAddress machineIP = IPAddress.Parse(GetIP());
Console.Clear();
Console.WriteLine(" - Starting IlanChat server on IP {0}", machineIP);
TcpListener server = null;
server = new TcpListener(machineIP, serverPort);
server.Start();
Byte[] buffer = new Byte[256];
String data = null;
Console.WriteLine("Successfully started IlanChat server!");
while (true) // first alpha - only one user at a time
{
Console.WriteLine();
Console.WriteLine("Waiting for connections..");
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("User connecting..");
Console.WriteLine("Receiving handshake data..");
data = null;
NetworkStream stream = client.GetStream();
int i;
while ((i = stream.Read(buffer, 0, buffer.Length)) != 0)
{
data = System.Text.Encoding.ASCII.GetString(buffer, 0, i);
Console.WriteLine("Received handshake data: {0}", data);
Console.WriteLine("Processing data.."); // sample handshake: - HANDSHAKE:nick:ip
string tempNick = data.Replace("HANDSHAKE:", "");
string[] userDetails = tempNick.Split(':'); // should store to 0:nick, 1:ip
Console.WriteLine("Received client nick: {0}", userDetails[0]);
Console.WriteLine("Received client IP: {0}", userDetails[1]);
break;
}
Thread.Sleep(1100); // sleep
buffer = System.Text.Encoding.ASCII.GetBytes(responseHandshake);
Console.WriteLine("Sending response handshake..");
stream.Write(buffer, 0, buffer.Length);
}
Is there a way to make the server accept multiple connections at once, and maintain them? And is there a way to make the client receive multiple messages at once and type while refreshing the messages?
You need to look at using threading (Task library, async/await) to do what you want. Try looking here:
https://codereview.stackexchange.com/questions/29000/c-console-chat-server-async-await-tcpclient-tcplistener-networkstream-asyn
To get you started, assuming the logic in your code is correct you want to split up the server/client, something like this:
static void RunServer()
{
List<string> clientIP = new List<string>();
List<string> clientNicks = new List<string>();
string responseHandshake = "hello";
Int32 serverPort = 1336;
IPAddress machineIP = IPAddress.Parse(GetIP());
Console.Clear();
Console.WriteLine(" - Starting IlanChat server on IP {0}", machineIP);
TcpListener server = null;
server = new TcpListener(machineIP, serverPort);
server.Start();
Byte[] buffer = new Byte[256];
String data = null;
Console.WriteLine("Successfully started IlanChat server!");
while (true) // first alpha - only one user at a time
{
Console.WriteLine();
Console.WriteLine("Waiting for connections..");
TcpClient client = server.AcceptTcpClient();
Task.Run(() => RunClient(client));
}
}
static void RunClient(TcpClient client)
{
Byte[] buffer = new Byte[256];
Console.WriteLine("User connecting..");
Console.WriteLine("Receiving handshake data..");
String data = null;
string responseHandshake = "hello";
NetworkStream stream = client.GetStream();
int i;
while ((i = stream.Read(buffer, 0, buffer.Length)) != 0)
{
data = System.Text.Encoding.ASCII.GetString(buffer, 0, i);
Console.WriteLine("Received handshake data: {0}", data);
Console.WriteLine("Processing data.."); // sample handshake: - HANDSHAKE:nick:ip
string tempNick = data.Replace("HANDSHAKE:", "");
string[] userDetails = tempNick.Split(':'); // should store to 0:nick, 1:ip
Console.WriteLine("Received client nick: {0}", userDetails[0]);
Console.WriteLine("Received client IP: {0}", userDetails[1]);
break;
}
Thread.Sleep(1100); // sleep
buffer = System.Text.Encoding.ASCII.GetBytes(responseHandshake);
Console.WriteLine("Sending response handshake..");
stream.Write(buffer, 0, buffer.Length);
}

Categories