I have developed TCP/IP Server in C# listening on port and a GPS device is sending the data to server.
Initially, the device sends the IMEI number to server and server acknowledges with 01. After receiving the acknowledgement by device, a new packet of data is sent to server.
I am able to get IMEI number by TCP Server and after sending acknowledgement, i am not able to receive new packet data from client. I am including my code below also. Please let me know where i am wrong.
I have tested using hercules tcp server tool and next data packet is receiving successfully but from my application it is not working.
try
{
IPAddress ipAdress = IPAddress.Parse(ConfigurationManager.AppSettings["Server"].ToString());
// You can use local IP as far as you use the
//same in client
// Initializes the Listener
TcpListener myList = new TcpListener(ipAdress, int.Parse(ConfigurationManager.AppSettings["Port"].ToString()));
for (; ; )
{ // Run forever, accepting and servicing connections
//Start Listeneting at the specified port
myList.Start();
Console.WriteLine("Server running - Port: 8000");
Console.WriteLine("Local end point:" + myList.LocalEndpoint);
Console.WriteLine("Waiting for connections...");
Socket socket = myList.AcceptSocket();
// When accepted
Console.WriteLine("Connection accepted from " + socket.RemoteEndPoint);
byte[] b = new byte[1000];
int k = socket.Receive(b);
Console.WriteLine("echoed {0} bytes.", k);
Console.WriteLine("Reading IMEI....");
string hexStr = ConvertAsciiToHex(Encoding.ASCII.GetString(b, 0, b.Length));
File.WriteAllText(#"C:\ClientFiles\testIMEI", hexStr);
ASCIIEncoding asen = new ASCIIEncoding();
string response = "01";
Console.WriteLine("Ackowledgement Data - " + response);
//
int sentBytes = socket.Send(asen.GetBytes(response));
Console.WriteLine("Acknowledgement data sent!\n");
int count = 0;
while (socket.Poll(-1, SelectMode.SelectRead))
{
b = new byte[1000];
k = socket.Receive(b);
if (k > 0)
{
count++;
Console.WriteLine("Reading Client Data - Count - " + count.ToString() + " and lenght " + k.ToString());
hexStr = ConvertAsciiToHex(Encoding.ASCII.GetString(b, 0, b.Length));
File.WriteAllText(#"C:\ClientFiles\testData" + count.ToString(), hexStr);
}
}
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
myList.Stop();
}
catch (Exception ex)
{
File.WriteAllText(#"C:\ClientFiles\Error.txt", ex.Message + "****" + ex.InnerException);
}
I don't see any error in the program, except these comments:
// Don't use the b.Length in this command:
string hexStr = ConvertAsciiToHex(Encoding.ASCII.GetString(b, 0, b.Length));
// use k instead, the numbers actually read, not the length of the buffer.
string hexStr = ConvertAsciiToHex(Encoding.ASCII.GetString(b, 0, k));
while (socket.Poll(-1, SelectMode.SelectRead))
{
// b has been allocated, don't need this
// b = new byte[1000];
k = socket.Receive(b);
if (k > 0)
{
count++;
Console.WriteLine("Reading Client Data - Count - " + count.ToString() + " and lenght " + k.ToString();
// use k not Length
hexStr = ConvertAsciiToHex(Encoding.ASCII.GetString(b, 0, k /*b.Length*/));
File.WriteAllText(#"C:\ClientFiles\testData" + count.ToString(), hexStr);
}
}
Do you know if the Poll command ever returns? May be it raises an error and you are missing that one. Check it out.
Related
So I am writing a c# client server program where the client receives information from the server, however the client appears to try to send information rather than receive after the successfully connect
public void SL_Click(object sender, EventArgs e)
{
try
{
TcpClient tcpclnt = new TcpClient();
tcpclnt.Connect(RecieveIP.Text, 8001); // use the ipaddress as in the server program
MessageBox.Show("Connected");
String str = Console.ReadLine();
Stream stm = tcpclnt.GetStream();
ASCIIEncoding asen = new ASCIIEncoding();
byte[] ba = asen.GetBytes(str);
MessageBox.Show("Listening for information......");
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]));
string toattk = str.ToString();
I think this, as the client and server do successfully connect, but the the message sent from the server is never actually recieved.
Server code for action when it connects and sends the message to the other computer:
private void Connectnattk_DoWork(object sender, DoWorkEventArgs e)
{
try
{
IPAddress ipAd = IPAddress.Parse(ipv4.Text); //use local m/c IP address, and use the same in the client
/* Initializes the Listener */
TcpListener myList = new TcpListener(ipAd, 8001);
/* Start Listeneting at the specified port */
myList.Start();
MessageBox.Show("The server is running at port 8001...");
MessageBox.Show("The local End point is :" + myList.LocalEndpoint);
MessageBox.Show("Looking for other computer");
Socket s = myList.AcceptSocket();
Console.WriteLine("Found buddy " + s.RemoteEndPoint);
ASCIIEncoding asen = new ASCIIEncoding();
s.Send(asen.GetBytes(satt.Text));
MessageBox.Show("The command " + satt.Text + " was sent to the computer with IP address " + ipv4.Text);
byte[] b = new byte[100];
int k = s.Receive(b);
for (int i = 0; i < k; i++)
Console.Write(Convert.ToChar(b[i]));
/* clean up */
s.Close();
myList.Stop();
}
catch (Exception)
{
MessageBox.Show("Could not find other computer.");
}
They connect no problem, but the message sent from the server never appears on the client. I surmise this is because the client is trying to send a response back rather than receiving the message sent by the server. Or are there other reasons why the message is not received despite the computers connected? Thank you.
I am trying to learn the server/client paradigm. I have created a server that listens for connection and input on given port.
My problem is that, when a client connects and sends a message, the server closes the connection, and stops listening for input. What I want, is that when a clients sends a message, the sever should not close the connection, but still keep getting input from the connected client. I know that I can only handle one client at a time, since I am not creating a Thread for each client, but this should not cause the server to close connection as soon as the client sends a message.
Here is my server code:
public void startServer() {
try {
IPAddress iAd = IPAddress.Parse("127.0.0.10");
TcpListener tcpListner = new TcpListener(iAd, 9000);
tcpListner.Start();
Console.WriteLine("The server is running on port: 9000");
Console.WriteLine("The local End point is: " + tcpListner.LocalEndpoint + "\nWaiting for a connection");
Socket socket = tcpListner.AcceptSocket();
Console.WriteLine("\nConnection from client: " + socket.RemoteEndPoint);
byte[] b =new byte[100];
int k = socket.Receive(b);
for (int i=0;i<k;i++) {
Console.Write("Recieved: " + Convert.ToChar(b[i]));
}
ASCIIEncoding asen=new ASCIIEncoding();
socket.Send(asen.GetBytes("The string was recieved by the server."));
Console.WriteLine("\nSent Acknowledgement");
/* clean up */
socket.Close();
tcpListner.Stop();
} catch(Exception e) {
Console.WriteLine(e.Message);
}
}
And the client code
public void StartClient(string servToConnectTo, int port) {
try{
client.Connect(servToConnectTo, port);
Console.WriteLine("Connected to server: " + servToConnectTo + " on port: " + port);
Console.WriteLine ("Write input to server...");
String input = Console.ReadLine();
Stream stream = client.GetStream();
ASCIIEncoding asen = new ASCIIEncoding();
byte[] b = asen.GetBytes(input);
Console.WriteLine("Sending...");
stream.Write(b, 0, b.Length);
byte[] bb = new byte[100];
int k = stream.Read(bb, 0, 100);
for(int i = 0; i < k; i++) {
Console.Write(Convert.ToChar(bb[i]));
}
client.Close();
} catch (Exception e) {
Console.WriteLine (e.Message);
}
}
I guess I need a while loop some place, but not sure where
Pre:
I have client and server. I send some data from client (win forms) to the server (console). I send data using this on the client:
try {
sock = client.Client;
data = "Welcome message from client with proccess id " + currentProcessAsText;
sock.Send(Encoding.ASCII.GetBytes(data));
}
catch
{
// say there that
}
On server I receive data by this:
private void ServStart()
{
Socket ClientSock; // сокет для обмена данными.
string data;
byte[] cldata = new byte[1024]; // буфер данных
Listener = new TcpListener(LocalPort);
Listener.Start(); // начали слушать
Console.WriteLine("Waiting connections [" + Convert.ToString(LocalPort) + "]...");
for (int i = 0; i < 1000; i++)
{
Thread newThread = new Thread(new ThreadStart(Listeners));
newThread.Start();
}
}
private void Listeners()
{
Socket socketForClient = Listener.AcceptSocket();
string data;
byte[] cldata = new byte[1024]; // буфер данных
int i = 0;
if (socketForClient.Connected)
{
string remoteHost = socketForClient.RemoteEndPoint.ToString();
Console.WriteLine("Client:" + remoteHost + " now connected to server.");
while (true)
{
i = socketForClient.Receive(cldata);
if (i > 0)
{
data = "";
data = Encoding.ASCII.GetString(cldata).Trim();
if (data.Contains("exit"))
{
socketForClient.Close();
Console.WriteLine("Client:" + remoteHost + " is disconnected from the server.");
break;
}
else
{
Console.WriteLine("\n----------------------\n" + data + "\n----------------------\n");
}
}
}
}
}
Server start threads and starting listening socket on each.
Problem:
When client connects or sends message, server outputs message received + ~ 900 spaces (because buffer is 1024). How I can get received data length and allocate so much memory as needed for this data?
Per the MSDN article, the integer returned by Receive is the number of bytes received (this is the value you have assigned to i).
If you change your while loop to be like this then you will have the value you are looking for:
int bytesReceived = 0;
while (true)
{
i = socketForClient.Receive(cldata);
bytesReceived += i;
if (i > 0)
{
// same code as before
}
}
I'm trying to implement ping based on udp packets with C#. The idea is to send udp packets to wrong port and get back ICMP packets contating Port unreachable error. And the time elapsed between seding the udp packet and recieveing the icmp packet is a ping time. I do it like that:
// Start building the headers
//Console.WriteLine("Building the packet header...");
int messageSize = 64;
byte[] builtPacket, payLoad = new byte[messageSize];
UdpHeader udpPacket = new UdpHeader();
ArrayList headerList = new ArrayList();
Socket rawSocket = null;
SocketOptionLevel socketLevel;
// Initialize the payload
//Console.WriteLine("Initialize the payload...");
for (int i = 0; i < payLoad.Length; i++)
payLoad[i] = (byte)'0';
// Fill out the UDP header first
//Console.WriteLine("Filling out the UDP header...");
udpPacket.SourcePort = 33434;
udpPacket.DestinationPort = 33434;
udpPacket.Length = (ushort)(UdpHeader.UdpHeaderLength + messageSize);
udpPacket.Checksum = 0;
Ipv4Header ipv4Packet = new Ipv4Header();
// Build the IPv4 header
//Console.WriteLine("Building the IPv4 header...");
ipv4Packet.Version = 4;
ipv4Packet.Protocol = (byte)ProtocolType.Udp;
ipv4Packet.Ttl = 30;
ipv4Packet.Offset = 0;
ipv4Packet.Length = (byte)Ipv4Header.Ipv4HeaderLength;
ipv4Packet.TotalLength = (ushort)Convert.ToUInt16(Ipv4Header.Ipv4HeaderLength + UdpHeader.UdpHeaderLength + messageSize);
ipv4Packet.SourceAddress = sourceAddress;
ipv4Packet.DestinationAddress = destAddress;
// Set the IPv4 header in the UDP header since it is required to calculate the
// pseudo header checksum
//Console.WriteLine("Setting the IPv4 header for pseudo header checksum...");
udpPacket.ipv4PacketHeader = ipv4Packet;
// Add IPv4 header to list of headers -- headers should be added in th order
// they appear in the packet (i.e. IP first then UDP)
//Console.WriteLine("Adding the IPv4 header to the list of header, encapsulating packet...");
headerList.Add(ipv4Packet);
socketLevel = SocketOptionLevel.IP;
// Add the UDP header to list of headers after the IP header has been added
//Console.WriteLine("Adding the UDP header to the list of header, after IP header...");
headerList.Add(udpPacket);
// Convert the header classes into the binary on-the-wire representation
//Console.WriteLine("Converting the header classes into the binary...");
builtPacket = udpPacket.BuildPacket(headerList, payLoad);
// Create the raw socket for this packet
//Console.WriteLine("Creating the raw socket using Socket()...");
rawSocket = new Socket(sourceAddress.AddressFamily, SocketType.Raw, ProtocolType.Udp);
// Bind the socket to the interface specified
//Console.WriteLine("Binding the socket to the specified interface using Bind()...");
IPAddress bindAddress = IPAddress.Any;
rawSocket.Bind(new IPEndPoint(bindAddress, 0));
// Set the HeaderIncluded option since we include the IP header
//Console.WriteLine("Setting the HeaderIncluded option for IP header...");
rawSocket.SetSocketOption(socketLevel, SocketOptionName.HeaderIncluded, 1);
rawSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 1000);
Stopwatch timer = new Stopwatch();
try {
for (int i = 0; i < 5; i++) {
timer.Reset();
timer.Start();
int rc = rawSocket.SendTo(builtPacket, new IPEndPoint(destAddress, 0));
Console.WriteLine("Sent {0} bytes to {1}", rc, destAddress);
Socket icmpListener = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);
icmpListener.Bind(new IPEndPoint(sourceAddress, 0));
icmpListener.IOControl(IOControlCode.ReceiveAll, new byte[] { 1, 0, 0, 0 }, new byte[] { 1, 0, 0, 0 });
icmpListener.Shutdown(SocketShutdown.Send);
byte[] buffer = new byte[4096];
EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
try {
int bytesRead = icmpListener.ReceiveFrom(buffer, ref remoteEndPoint);
timer.Stop();
Console.WriteLine("Recieved " + bytesRead + " bytes from " + destAddress + " in " + timer.ElapsedMilliseconds + "ms\n");
}
catch {
Console.WriteLine("Server is not responding!");
}
finally {
icmpListener.Close();
}
}
}
catch (SocketException err) {
Console.WriteLine("Socket error occurred: {0}", err.Message);
}
finally {
rawSocket.Close();
}
And it works from time to time. The thing is that some web-sites send me an icmp packet and some not. Actually at first they also were not sending then I used Windows ping to ping them and tracert to traceroute them. And changed port number and it worked. But not for all. I can ping only google.com and one more site but others don't send icmp packet back. The same situation with local network computers I tried to ping. I send udp packet and don't get icmp back.
I used wireshark to watch packets flying.
What am I doing wrong in here?
I have written a code for client server using tcp/sockets in c# which is working perfectly fine. My problem is that why I am able to send only limited size data from client to server at a single instance.
Following is my server code
public class AsynchIOServer
{
// server port number
const int port = 8001;
// server ip address
const string ip = "127.0.0.1";
const int maxBuffer = 10000;
static IPAddress ipAddress = IPAddress.Parse(ip);
static TcpListener tcpListener = new TcpListener(ipAddress, port);
static void Listeners()
{
try
{
Socket socketForClient = tcpListener.AcceptSocket();
if (socketForClient.Connected)
{
Console.WriteLine("Client : " + socketForClient.RemoteEndPoint + " is now connected to server.");
NetworkStream networkStream = new NetworkStream(socketForClient);
System.IO.StreamWriter streamWriter = new System.IO.StreamWriter(networkStream);
System.IO.StreamReader streamReader = new System.IO.StreamReader(networkStream);
while (true)
{
string theString = streamReader.ReadLine();
if (theString != "exit")
{
// original message from client
Console.WriteLine("------------------------------------------------------------------------------");
Console.WriteLine("Message recieved from client(" + socketForClient.RemoteEndPoint + ") : " + theString);
// ASCII code for the message from client
Console.Write("ASCII Code for message is : ");
foreach (char c in theString)
{
Console.Write(System.Convert.ToInt32(c) + " ");
}
// Hex value of message from client
string hex = "";
foreach (char c in theString)
{
int tmp = c;
hex += String.Format("{0:x2}", (uint)System.Convert.ToUInt32(tmp.ToString()));
}
Console.WriteLine();
Console.WriteLine("Hex Code for the message from client : " + hex);
//sending acknowledgement to client
Console.WriteLine();
socketForClient.Send(new ASCIIEncoding().GetBytes(/*"The string was recieved from Client(" + socketForClient.RemoteEndPoint + ") : " + */theString));
} // end of if loop
// if exit from client
else
{
Console.WriteLine();
Console.WriteLine("Client " + socketForClient.RemoteEndPoint + " has exited");
break;
}
} // end of while loop
streamReader.Close();
networkStream.Close();
streamWriter.Close();
} // end of if loop
socketForClient.Close();
Console.WriteLine();
// Console.WriteLine("Press any key to exit from server program");
Console.ReadKey();
} // end of try loop
catch (Exception e)
{
Console.WriteLine("The process failed: {0}", e.ToString());
Console.WriteLine("Message not received from client");
}
} // end of Listener loop
// Number of clients that can connect to the server
public static void Main()
{
tcpListener.Start();
Console.WriteLine("********** This is the Server program **********");
Console.Write("Number of Clients that can connect to Server : ");
int numberOfClientsYouNeedToConnect = int.Parse(Console.ReadLine());
for (int i = 0; i < numberOfClientsYouNeedToConnect; i++)
{
Thread newThread = new Thread(new ThreadStart(Listeners));
newThread.Start();
}
Console.WriteLine();
} // end of Min Loop
} // end of public class AsynchIOServer
while my client code is
public class Client
{
// For acknowledgement from server
const int maxBuffer = 1000;
static public void Main(string[] Args)
{
// ip address of server to which client should be connected
string ip;
// port number at which server is listening for client connection
int port;
Console.Write("Enter the ip address: ");
ip = Console.In.ReadLine();
Console.Write("Enter the port number: ");
port = int.Parse(Console.In.ReadLine());
TcpClient socketForServer;
try
{
// connect to server at ipaddress ip and port number port
socketForServer = new TcpClient(ip, port);
}
catch
{
Console.WriteLine("Failed to connect to server at {0}:{1}", ip , port);
Console.ReadLine();
return;
}
// Initializing StreamReader and StreamWriter for sending or reading message from server
NetworkStream networkStream = socketForServer.GetStream();
System.IO.StreamReader streamReader = new System.IO.StreamReader(networkStream);
System.IO.StreamWriter streamWriter = new System.IO.StreamWriter(networkStream);
try
{
Console.WriteLine();
Console.WriteLine("---Begin sending message(type 'exit' to disconnect from server)---");
Console.WriteLine();
Console.Write("Type message : ");
string str = Console.ReadLine();
while (str != "exit")
{
streamWriter.WriteLine(str);
streamWriter.Flush();
// For receiving acknowledgement from server
byte[] receiveBuffer = new byte[maxBuffer];
int k = networkStream.Read(receiveBuffer, 0, maxBuffer);
for (int i = 0; i < k; i++)
Console.Write(/*Convert.ToChar(*/receiveBuffer[i]);
Console.WriteLine();
Console.WriteLine("------------------------------------------------------");
Console.Write("Type message : ");
str = Console.ReadLine();
}
// For client to close connection with server
if (str == "exit")
{
streamWriter.WriteLine(str);
streamWriter.Flush();
}
} // end of try loop
catch
{
Console.WriteLine("Exception reading from Server");
}
// exit the client
networkStream.Close();
Console.WriteLine("Press any key to exit from client program");
Console.ReadKey();
} // End of Main loop
} // End of public class Client
Now when I run my program I enter following binary to be sent from client as first message
Type message : 11111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111
Problem is that it doesn't allow me enter more binary data. I can send more binary data if I want to send by pressing enter and then sending as 2nd message. But I want to send it as single message. So is their any limit to send more data at single instance over tcp/sockets?
Your assessment of the problem is wrong. There are no messages -- TCP has no such thing as application-level messages because TCP is not a message protocol, it's a byte stream protocol that provides a stream of bytes, not messages. There is no such thing as "send it as single message" nor is there such as thing as "sending as 2nd message". It's just sending bytes and receiving bytes. If you want to receive more bytes, call receive again.
If you want to implement messages, you can do so. But you have to do it. You have to define, specify, and implement a protocol that sends and receives messages on top of TCP. You have to specify how messages will be delimited, send delimited messages, and write receive code to detect the delimiters and assemble the received byte stream into messages. It won't happen by itself.
The simplest solution is to read and write lines delimited by newline characters, assuming your "messages" can't contain newlines.
That has to do with the ReadLine method limiting input to 256 characters, see Remarks section for a workaround:
http://msdn.microsoft.com/en-us/library/system.console.readline.aspx
edit: typo