Any suggestions on testing a TCP client listener. What I'm looking for is actual network stats like "payload size", "time-out values", "actual payload bytes received from server".
public static void tcpConnect() {
int port = 12345;
IPEndPoint ipep = new IPEndPoint(
IPAddress.Parse("xx.xx.xx.xx"), port);
Socket server = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
IPGlobalProperties _ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
TcpConnectionInformation[] _tcpConnInfoArray = _ipGlobalProperties.GetActiveTcpConnections();
// bool isAvaiable = true;
try
{
server.Connect(ipep);
}
catch (SocketException e)
{
Console.WriteLine("Unable to connect to server");
Console.WriteLine(e.ToString());
return;
}
NetworkStream ns = new NetworkStream(server);
if (ns.CanRead)
{
foreach (TcpConnectionInformation tcpConnInfo in _tcpConnInfoArray)
{
if (tcpConnInfo.LocalEndPoint.Port == port)
{
//isAvaiable = false;
Console.WriteLine("Error: Can't Read from Port");
break;
}
Console.Write("Local endpoint: {0} ", tcpConnInfo.LocalEndPoint.Address);
Console.Write("Remote endpoint: {0} ", tcpConnInfo.RemoteEndPoint.Address);
Console.Write("{0}", tcpConnInfo.State);
}
}
else
{
Console.WriteLine("Error: Can't Read from Socket");
ns.Close();
return;
}
while (true)
{
string input = Console.ReadLine();
if (input == "exit")
break;
if (ns.CanWrite)
{
Console.WriteLine("NS Can write");
ns.Flush();
}
}
Console.WriteLine("Disconnection from server");
ns.Close();
server.Shutdown(SocketShutdown.Both);
server.Close();
}
}
So if I read correctly the real aim is to monitor the connection to see if it is still alive? We all know TCP is a state-full protocol. This means the "socket" must remain open. So you client will have a socket which is open. The TcpClient is just a nice wrapper that give you the ability to read and write to the socket. From the MS API page we can see there is an Active property. As the documentation reads, this is not updated if the remote disconnects... this is too bad and perhaps the problem you have. However they give the advise that if you want to watch the socket you will see if the remote disconnects. You can do this using the Connected property.
I know that not going to be the level of control you want, who wants to just see the TCP Client?? So get right at the Socket!!! once you have the socket you can have full control and viability over the connection. This should make you happy!!
Related
I'm trying to use generic IP socket objects in .NET. Connecting one of my sockets to another one and sending a few ping-pong messages works just fine.
But now I've implemented a server socket and somehow managed to create Schrödinger's socket.
The server socket handles the incoming connection request just fine, but the connecting socket seems to be connected when I check once but doesn't even have a RemoteEndpoint - though is showing "Connected = true" and it's disconnected when I check the 2nd time.
All sockets are initialized using this function:
private void initSocket() {
if (_socket != null) {
_socket.Dispose();
}
_socket = new Socket(_ownIP.AddressFamily, _socketType, _protocolType);
_socket.Bind(new IPEndPoint(_ownIP, _ownPort));
}
The _socketType is Stream and the _protocolType is Tcp in this case.
The connect function:
public bool connect(string ip, int port, int retries = 3) {
if (_isWaiting) {
throw new InvalidOperationException("Can't connect, when the socket is already waiting for clients.");
}
_wasWaiting = false;
initSocket();
_otherIP = IPAddress.Parse(ip);
_otherPort = port;
IPEndPoint endpoint = new IPEndPoint(_otherIP, _otherPort);
for (int i = 0; i < retries; i++) {
try {
IAsyncResult result = _socket.BeginConnect(endpoint, null, null);
bool success = result.AsyncWaitHandle.WaitOne(_connectTimeout, true);
if (_socket.Connected) {
_socket.EndConnect(result);
_isConnected = true;
return true;
}
else {
_socket.EndConnect(result);
}
}
catch (SocketException e) {
Console.WriteLine(e.Message);
}
}
return false;
}
The server uses this wait function to accept more clients:
private void wait() {
while (_isWaiting) {
try {
_socket.Listen(1);
var newSocket = _socket.Accept();
var newClient = new IPSocket(newSocket, _socketType, _protocolType, new MessageReceivedDelegate(clientReceivedMessage), true);
_clients.Add(newClient.PartnerIP + ":" + newClient.PartnerPort, newClient);
clientConnected(newClient.PartnerIP, newClient.PartnerPort);
while (true) {
Thread.Sleep(10);
}
}
catch (System.Net.Sockets.SocketException ex) {
//Need to find out which one is thrown when no client for accepting available
if (ex.ErrorCode == 2) {
}
Thread.Sleep(10);
}
catch {
Thread.Sleep(10);
}
}
}
The newSocket variable is connected at first and has a valid RemoteEndpoint, but the socket that's connected doesn't route back to newSocket.
I thought that maybe the connection resets when the server socket tries to accept new sockets, so I added the infinite wait loop - which didn't help.
So why does the connecting socket not have any RemoteEndpoint? (it's shown as null)
Since people usually recommend to accept the connection, handle data, close connection:
I want to keep the connection alive and I have to - not doing this is at the time not a solution that I'd consider.
So I have the code listed below for server client communication It works fine as long as you start both programms on the same PC but if I try to connect two seperate Pcs it doesn't work does anyone know where I have to put in the ip? I added some Console.Writelines to getter with there outputs as a comment
// ExecuteClient() Method
static void ExecuteClient(string message)
{
try
{
// Establish the remote endpoint
// for the socket. This example
// uses port 11111 on the local
// computer.
IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName());
Console.WriteLine(ipHost); //System.Net.IPHostEntry
IPAddress ipAddr = ipHost.AddressList[0];
Console.WriteLine(ipHost.AddressList.ToString()); //System.Net.IPAddress[]
Console.WriteLine(ipAddr); //gives back an ip v6 address
IPEndPoint localEndPoint = new IPEndPoint(ipAddr, 11111);
Console.WriteLine(localEndPoint);
// Creation TCP/IP Socket using
// Socket Class Costructor
Console.WriteLine("AddressFamily: " + ipAddr.AddressFamily.ToString()); //InterNetworkV6
Socket sender = new Socket(ipAddr.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
try
{
// Connect Socket to the remote
// endpoint using method Connect()
sender.Connect(localEndPoint);
// We print EndPoint information
// that we are connected
Console.WriteLine("Socket connected to -> {0} ",
sender.RemoteEndPoint.ToString());
// Creation of messagge that
// we will send to Server
byte[] messageSent = Encoding.ASCII.GetBytes("<EOF> " + message);
int byteSent = sender.Send(messageSent);
// Data buffer
byte[] messageReceived = new byte[1024];
// We receive the messagge using
// the method Receive(). This
// method returns number of bytes
// received, that we'll use to
// convert them to string
int byteRecv = sender.Receive(messageReceived);
Console.WriteLine("Message from Server -> {0}",
Encoding.ASCII.GetString(messageReceived,
0, byteRecv));
// Close Socket using
// the method Close()
sender.Shutdown(SocketShutdown.Both);
sender.Close();
}
// Manage of Socket's Exceptions
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());
}
}
//ExecuteServer method
public static void ExecuteServer()
{
// Establish the local endpoint
// for the socket. Dns.GetHostName
// returns the name of the host
// running the application.
IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddr = ipHost.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddr, 11111);
// Creation TCP/IP Socket using
// Socket Class Costructor
Socket listener = new Socket(ipAddr.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
try
{
// Using Bind() method we associate a
// network address to the Server Socket
// All client that will connect to this
// Server Socket must know this network
// Address
listener.Bind(localEndPoint);
// Using Listen() method we create
// the Client list that will want
// to connect to Server
listener.Listen(10);
while (true)
{
//Console.WriteLine("Waiting connection ... ");
// Suspend while waiting for
// incoming connection Using
// Accept() method the server
// will accept connection of client
Socket clientSocket = listener.Accept();
// Data buffer
byte[] bytes = new Byte[1024];
string data = null;
while (true)
{
int numByte = clientSocket.Receive(bytes);
data += Encoding.ASCII.GetString(bytes,
0, numByte);
if (data.IndexOf("<EOF>") > -1)
break;
}
Console.WriteLine("Text received -> {0} ", data);
if(data == "<EOF> " + "kill")
{
Application.Exit();
} else if (data == "<EOF> " + "test")
{
Console.Writeline("It works!");
} else
{
byte[] message = Encoding.ASCII.GetBytes("Error 404 message not found!");
// Send a message to Client
// using Send() method
clientSocket.Send(message);
Messagebox1();
}
// Close client Socket using the
// Close() method. After closing,
// we can use the closed Socket
// for a new Client Connection
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();
}
}
catch (Exception e)
{
//Console.WriteLine(e.ToString());
}
}
you can use something like this:
this.clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
this.clientSocket.Connect(new IPEndPoint(System.Net.IPAddress.Parse(ip), int.Parse(port)));
and pass the ip address to the "ip" variable.
What I am trying to do is just check the messages that the client is sending.
what I want is to maintain the socket that was created open and just check the get message that the client send from time to time.
I am using System.Net.Sockets only, I want to make an implementation based on barkeley sockets.
Here is my code,
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Runtime.Remoting.Metadata.W3cXsd2001;
namespace Socket_v1._0
{
class Program
{
private const int BUFSIZE = 200;// Size of receive buffer
private const int BACKLOG = 5; // O valor backlog define o número de pedidos de conexão que podem ser mantidos em espera sem serem aceites pela "system-call" accept.
static void Main(string[] args)
{
int servPort = 8070; //port number
Socket server = null;
try
{
// Create a socket to accept client connections
server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(new IPEndPoint(IPAddress.Any, servPort));
server.Listen(BACKLOG);
}
catch (SocketException se)
{
Console.WriteLine(se.ErrorCode + ": " + se.Message);
Environment.Exit(se.ErrorCode);
}
//for now the server socket is waiting for connections
byte[] rcvBuffer = new byte[BUFSIZE]; // definir buffer
int bytesRcvd = 0 ; // numero de bytes recebidos
for (; ; )
{ // Run forever, accepting and servicing connections
Socket client = null;
try
{
client = server.Accept(); // Get client connection
Console.Write("Handling client at " + client.RemoteEndPoint + " - ");
do {
bytesRcvd = client.Receive(rcvBuffer, 0, rcvBuffer.Length, SocketFlags.None);
string s = Encoding.ASCII.GetString(rcvBuffer, 0, bytesRcvd);
}while (true);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
client.Close();
}
}
}
}
}
So the client send a http get from time to time, i want to see those messages,
for now for the first time this runs the string gets the http get, and because I am maintaining the socket open, I want to wait for the next message (do{}(while(true))).
it goes back to the client.receive, and stops.
after detecting another message from the client it enters in forever loop and the string is empty.
I want something similar to a chat, where the client send messages and the server display the message.
So after opening the socket, what should i do to get the message from the client, then display it , then wait for another message?
One other thing that is bugging me is the client http get:
this is the http get
GET /iclock/cdata?SN=2182682370001&options=all&pushver=2.1.2&language=80 HTTP/1.1
Host: 192.168.1.43:8070
User-Agent: iClock Proxy/1.09
Connection: close
Accept: * / *
What does it mean when it says connection close? do i need create a new socket every time the client want to send a request?
Try to figure it out, i did some changes on the code, inside the do while i have got this
while ((bytesRcvd = client.Receive(rcvBuffer/*, 0, rcvBuffer.Length, SocketFlags.None*/)) > 0)
{
totalBytesEchoed += bytesRcvd;
string s = Encoding.ASCII.GetString(rcvBuffer, 0, bytesRcvd);
Console.WriteLine(s);
}
Image:
so in the image i have got wireshark running and my console app.
according to wireshark the client had tried to send 2 http request, but according to the console it only displayed one...
i want to display the two calls..
a few years ago, i did some exercises about sockets in c language.
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void main(void)
{
struct sockaddr_in me, from;
int newSock, sock = socket(AF_INET, SOCK_STREAM, 0);
int adl = sizeof(me);
char linha[81];
bzero((char *) &me, adl);
me.sin_family = AF_INET;
me.sin_addr.s_addr = htonl(INADDR_ANY ); /* endereco IP local */
me.sin_port = htons(8450); /* porta local */
if (-1 == bind(sock, (struct sockaddr *) &me, adl))
{
close(sock);
puts("Porta ocupada");
exit(1);
}
listen(sock, 5);
newSock = accept(sock, (struct sockaddr *) &from, &adl);
close(sock);
do
{
read(newSock, linha, 81);
puts(linha);
} while (strcmp(linha, "exit"));
close(newSock);
}
this is in c, so as you can see,after the accept the socket stays open, and the client send the message, it only close the socket when the user send exit to the server...
there may be times where the client doesnt send...but the socket is still open, and when it detects
this is an example of what i want to achive, using the system.net.sockets library,,,
thanks
There are two kinds of sockets: The socket that you use to listen (it is never connected) and the sockets that correspond to connections (each socket represents one connection).
Accept returns you a connected socket to the client that was just accepted. Each call to Accept accepts a new , independent client.
If you want to handle more than one client at a time (which is almost always required) you must ensure that a call to Accept is pending at all times so that new clients can be accepted.
A simple model to achieve this is to accept in a loop forever and start a thread for each client that you accepted:
while (true) {
var clientSocket = listeningSocket.Accept();
Task.Factory.StartNew(() => HandleClient(clientSocket));
}
It might very well be that the client closes the connection.
To detect this on the server side you need to test the result of the call to Receive() against 0.
From MSDN's documentation on Receive() (emphasis by me):
If you are using a connection-oriented Socket, the Receive method will read as much data as is available, up to the number of bytes specified by the size parameter. If the remote host shuts down the Socket connection with the Shutdown method, and all available data has been received, the Receive method will complete immediately and return zero bytes.
From my experience, every time client disconnects from server/listener, this will be registrered on server as SocketException - client has forcibly disconnected. What I do at the moment is just try to catch this and "nicelly" ignore it (log/display some sort of message or run an action to inform the user about this).
Have a look at your code, slightly refactored. Try to run it and see what is happening. I have added some comments to explain a bit. Hope this will help.
There is also class called TcpListenner in .NET you can use to implement behavior you require.
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace SimpleListener
{
class Program
{
const int PORT = 8070;
const int BACKLOG = 5;
static Socket socket;
private static byte[] rcvBuffer;
private static int bytesRcvd;
private static string message;
static void Main(string[] args)
{
try
{
StartListener();
Listen();
}
catch (Exception ex)
{
ShowMessage(ex.Message);
}
}
private static void StartListener()
{
try
{
//Initialize socket and start listenning
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(new IPEndPoint(IPAddress.Any, PORT));
socket.Listen(BACKLOG);
ShowMessage("I'm listenning now..");
}
catch (Exception)
{
throw;
}
}
private static void Listen()
{
try
{
rcvBuffer = new Byte[256];
bytesRcvd = 0;
message = string.Empty;
//Start listnening/waiting for client to connect
while (true)
{
var client = socket.Accept();
ShowMessage("Client with IP " + client.RemoteEndPoint.ToString() + " connected!");
//Client has connected, keep receiving/displaying data
while (true)
{
SocketError rcvErrorCode;
bytesRcvd = 0;
message = string.Empty;
bytesRcvd = client.Receive(rcvBuffer, 0, rcvBuffer.Length, SocketFlags.None);
if (rcvErrorCode != SocketError.Success)
{
Console.WriteLine("Client with IP " + client.RemoteEndPoint.ToString() + " disconnected!");
break;
}
message = Encoding.ASCII.GetString(rcvBuffer, 0, bytesRcvd);
Console.WriteLine(DateTime.Now.ToLongTimeString() + " - " + message);
}
}
}
catch (Exception)
{
throw;
}
}
private static void ShowMessage(string message)
{
Console.WriteLine(message);
Console.WriteLine();
}
}
}
I want a chat application in C# Client and in Java Server
I go through C# Client but I got some Error when I response to Java Server I get the error#
cannot access a disposed object object name='System.Net.Socket.Socket'
class Program
{
static void Main(string[] args)
{
byte[] bytes = new byte[1024];// data buffer for incoming data
// connect to a Remote device
try
{
// Establish the remote end point for the socket
IPHostEntry ipHost = Dns.Resolve("localhost");
IPAddress ipAddr = ipHost.AddressList[0];
IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, 95);
Socket Socketsender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// Connect the socket to the remote endpoint
Socketsender.Connect(ipEndPoint);
Console.WriteLine("\n\n___________________Client Server Chat Application__________________________");
Console.WriteLine("___________________________________________________________________________");
Console.WriteLine("\nSocket Connecting To Java Server...." + Socketsender.RemoteEndPoint.ToString());
// Console.ReadLine();
string data = null;
while (true)
{
//Recieved from Java Server Message
int bytesRec = Socketsender.Receive(bytes);
Console.WriteLine("\nJava Server:: {0}", Encoding.ASCII.GetString(bytes, 0, bytesRec));
// Console.ReadLine();
Console.Write("C# Client ::"); // Prompt
string line = Console.ReadLine();
byte[] sendToServer = Encoding.ASCII.GetBytes(line);
// Send the data through the socket
int intByteSend = Socketsender.Send(sendToServer);
// Socketsender.Shutdown(SocketShutdown.Both);
Socketsender.Close();
Console.WriteLine("____________________________________________________________________________");
Console.WriteLine("_________________________End Chat___________________________________________");
// Socketsender.Shutdown(SocketShutdown.Both);
Socketsender.Close();
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
Console.ReadLine();
}
}
You are closing your socket (Socketsender) in he while loop, and then—in the next iteration—calling Receive on it.
Once a socket is closed it is dead,1 and cannot be used for anything. You would need to create a new socket and connect it to the server.
Or better, keep the first socket open.
(You also are performing the close twice, but I'm assuming that is a transcription error.)
1 Insert dead parrot here.
I am new to programming and I am working on an asynchronous client server application.
I can send a message to the server from the client, but when I receive the data to the server (OnDataReceived Method) and try to send the same data back to the client (for testing purposes) I can't.
Not sure what other info I need to give, so please let me know, I don't mean to be vague.
SERVER CODE
public void OnDataReceived(IAsyncResult asyncResult)
{
try
{
SocketPacket socketData = (SocketPacket)asyncResult.AsyncState;
int iRx = 0;
iRx = socketData.currentSocket.EndReceive(asyncResult);
char[] chars = new char[iRx];
Decoder decoder = Encoding.UTF8.GetDecoder();
int charLen = decoder.GetChars(socketData.dataBuffer, 0, iRx, chars, 0);
String receivedData = new String(chars);
//BroadCast(receivedData);
this.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() => lbxMessages.Items.Add(receivedData)));
//Updated Code
this.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() => broadcast(receivedData)));
WaitForData(socketData.currentSocket);
}
catch (ObjectDisposedException)
{
System.Diagnostics.Debugger.Log(0, "1", "\n OnDataRecieved: Socket has been closed\n");
}
catch (SocketException se)
{
MessageBox.Show(se.Message);
}
}
public class SocketPacket
{
public Socket currentSocket;
public byte[] dataBuffer = new byte[50];//allowing the 50 digist to be sent at once
}
private void WaitForData(Socket socket)
{
try
{
if (workerCallBack == null)
{
workerCallBack = OnDataReceived;
}
SocketPacket sckPack = new SocketPacket();
sckPack.currentSocket = socket;
socket.BeginReceive(sckPack.dataBuffer, 0, sckPack.dataBuffer.Length, SocketFlags.None, workerCallBack, sckPack);
}
catch(SocketException se)
{
MessageBox.Show(se.Message);
}
}
Updated in response to Andrew's reply
I have a method that will be invoked when a client is connected
private void OnClientConnect(IAsyncResult asyncResult)
{
try
{
//Here we complete/end the Beginaccept() asynchronous call by
//calling EndAccept() - which returns the reference to a new socket object
workerSocket[clientCount] = listenSocket.EndAccept(asyncResult);
//Let the worker socket do the further processing for the just connected client
WaitForData(workerSocket[clientCount]);
//Now increment the client count
++clientCount;
if (clientCount<4)//allow max 3 clients
{
//Adds the connected client to the list
connectedClients.Add(listenSocket);
String str = String.Format("Client # {0} connected", clientCount);
this.Dispatcher.Invoke((Action)(() =>
{
//Display this client connection as a status message on the GUI
lbxMessages.Items.Add(str);
lblConnectionStatus.Content =clientCount + " Connected";
}));
//Since the main Socket is now free, it can go back and wait for
//other clients who are attempting to connect
listenSocket.BeginAccept(OnClientConnect, null);
}
}
catch (ObjectDisposedException)
{
System.Diagnostics.Debugger.Log(0, "1", "\n OnClientConnection: Socket has been closed\n");
}
catch (SocketException)
{
HandleClientDisconnect(listenSocket);
}
}
(UPDATED)
ADDED METHOD TO BROADCAST MESSAGE RECEIVED BY SERVER BACK TO CLIENT
public void broadcast(string msg)
{
//foreach (Socket item in connectedClients)
//{
Socket broadcastSocket;
broadcastSocket = workerSocket[0]; //sends message to first client connected
byte[] broadcastBytes = null;
broadcastBytes = Encoding.ASCII.GetBytes(msg);
broadcastSocket.Send(broadcastBytes);
//}
}
There is two sockets involved in server-side TCP communication. First socket is a listening socket and you should use it only for accepting new request. Then every time you accept new request from the client you're getting another socket for every connection.
You trying to send data back via listening socket but not via socket that you accepted.
Sergey has it right. If you're looking to have one server handle multiple clients, then you'll need some sort of ServerTerminal class which can listen for new connections and then setup some sort of "connectedclient" class to handle IO to that socket. Your "OnDataReceived" method would be in the connectedclient class.
In your socket accept routine it should look something like:
private void OnClientConnection(IAsyncResult asyn)
{
if (socketClosed)
{
return;
}
try
{
Socket clientSocket = listenSocket.EndAccept(asyn);
ConnectedClient connectedClient = new ConnectedClient(clientSocket, this, _ServerTerminalReceiveMode);
connectedClient.StartListening();
In the accept routine you're passed a socket - i've named this "clientSocket". This is the socket you want to write to, not the listening socket.