Reputation: 352
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
Upvotes: 3
Views: 3447
Reputation: 4863
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();
}
}
}
Upvotes: 0
Reputation: 70931
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.
Upvotes: 1
Reputation: 171178
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));
}
Upvotes: 1