I tried to use single server to serve both pure C# socket client (without ssl) and secure websocket client (with required ssl - wss). How does my server detect which type of client to serving? My server is written in C# too.
I tried use the Available property of Socket class. Websocket clients often has larger value than pure socket clients, but it doesn't seem to work. The value of Available is not stable.
Socket ClientSocket = Server.Accept();
if (/* condition to decide type of socket client */) // I tried but not work: ClientSocket.Available > 100
{
NetworkStream _stream = new NetworkStream(ClientSocket);
var ssl = new SslStream(_stream, false);
this.Authenticate(ClientSocket, ssl, ServerCertificate);
// call StartClient() after authenticating successfully
}
else
{
StartClient(ClientSocket);
}
Related
I want to establish connection with server and communicate with ActiveMQ running on that server
I take code from MSDN:
TcpClient client = new TcpClient(machineName, port); // ActiveMQ is running on that port on the server
Console.WriteLine("Client connected.");
SslStream sslStream = new SslStream(
client.GetStream(),
false,
new RemoteCertificateValidationCallback(ValidateServerCertificate),
null
);
try
{
sslStream.AuthenticateAsClient(machineName, certificates, SslProtocols.Tls, true);
}
catch (AuthenticationException e)
{
Console.WriteLine("Exception: {0}", e.Message);
if (e.InnerException != null)
{
Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
}
Console.WriteLine("Authentication failed - closing the connection.");
client.Close();
return;
}
and I am able to establish connection. I send request to the server:
byte[] messsage = Encoding.UTF8.GetBytes("Hello from the client.<EOF>");
// Send hello message to the server.
sslStream.Write(messsage);
sslStream.Flush();
// Read message from the server.
string serverMessage = ReadMessage(sslStream);
Console.WriteLine("Server says: {0}", serverMessage);
In the response, server says:
?ActiveMQ y TcpNoDelayEnabled SizePrefixDisabled CacheSize ProviderName
ActiveMQ StackTraceEnabled PlatformDetails TJVM: 1.8.0_202, 25.202-b08, Oracle Corporation, OS: Windows Server
So, it means communication with Server AMQ established. My question is, how can I use now that AMQ channel for sending and receiving messages? Normally, I have to specify message queue I want to use. How and where I have to do that?
Should it be in message I send to server? Something like:
string message_queue = "test.message.tosend";
byte[] request = Encoding.UTF8.GetBytes(String.Format(<formatted queue name with message content>, machineName));
Example of code would be very much appreciated.
ActiveMQ is a message broker which supports lots of different messaging protocols (e.g. OpenWire, AMQP 1.0, STOMP, & MQTT). Each of these protocols is similar in that they support the exchange of messages between a client and the broker, but they are different in what specific functionality they support, their protocol handshakes, wire formats, etc.
For whatever reason you are not using any of the client implementations for these protocols. You are using the low level TcpClient which means you'll need to find the specification for the protocol you wish to speak (e.g. AMPQ 1.0, STOMP 1.2) and implement a client for it. Depending on the protocol you choose this could be a significant amount of work.
However, instead of reimplementing a client you could use one which already exists, e.g.:
AmqpNetLite
Stomp.Net
MQTTnet
I am using a TcpClient in C# to communicate with a server.
When I view the first SYN request in Wireshark, I see 12 bytes specifying 6 TCP Options in the following order:
-Maximum Segment size
-NOP
-Window Scale
-NOP
-NOP
-SACK Permitted
TCP_Options <<< A screenshot of the Wireshark capture
I am using the default constructor of the TcpClient object being passed into the function.
I believe there is a way to specify an option using the Socket.SetSocketOption Method (described here), however, I wish to remove these options to verify that the server doesn't require them to establish connections.
Is it possible to remove (or perhaps modify) the options that I am seeing in Wireshark?
Here is a small sample of how I am using the TcpClient (instantiated with defaults):
public static IPStatus PingThenConnect(TcpClient tcpClient, IPEndPoint serverEndpoint)
{
IPStatus ipStatus = IPStatus.Unknown;
// Ping the given IP Address
ipStatus = Network.PingIP(serverEndpoint.Address);
if (ipStatus == IPStatus.Success)
{
// Connect TcpClient to given endpoint.
tcpClient.Connect(serverEndpoint.Address, serverEndpoint.Port);
tcpClient.LingerState = new LingerOption(true, 10);
}
return ipStatus;
}
I've got a little problem with the .Net Sockets in C#.
I programmed a client and a server working with TCP.
As the client is opened it sends a handshake to the server. The server answers with it's state (clientexists, clientaccepted,...). After that the application sends a getdata-request, abandons the connection and listens for the server's 'response'. Now, the server builds a connection to the client and sends all the data the client needs.
The code and everything else works, but the problem:
On our company testserver it works fine, on the live server only the handshake works. After it the client doesn't receive any more data. Serverapplication is the same on both servers.
I thought the problem was caused by some firewall (server wants to build a tcp connection to the client -> not good), but the system administrator said there is no firewall that could block that.
Now I'm searching for a ('cheap') solution that doesn't take too much time and changes in code. If anyone knows how to theoretically solve that, that would be great.
BTW: I am not allowed to do anything on the live server other than run the serverapplication. I don't have the possibility to debug on this server.
I can't publish all of my code, but if you need to see specific parts of it, ask for it please.
---EDIT---
Client-Server communication
1) Client startup
Client send handshake (new tcp connection)
2) Server validates handshake and saves IP
Server responds with it's client state (same tcp connection)
3) Client acknowledges this response and abandons this connection
Client sends getdata-request (new tcp connection)
Client abandons this tcp connection, too
4) Server receives getdata-request and collects the needed data in the main database
Server sends all the collected data to the client (multiple tcp connections)
5) Client receives all data and displays it in it's GUI (multiple tcp connections and the order of the data is kept by working with AutoResetEvents and Counts of sockets to send)
This is the main part my code does. It's by far not the best but it was for me as I wrote it I guess. Step one, two and three work as intended. The processing of the data works fine, too.
Another thing i forgot to mention is that the solution uses two Ports '16777' and '16778'. One to receive/listen and one to send.
My code is based on the MSDN example of the asynchronous server and client.
Sending a handshake (and getdata-request)
public void BeginSend(String data)
{
try
{
StateObject state = new StateObject();
state.workSocket = sender;
byte[] byteData = Encoding.UTF8.GetBytes(data);
sender.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback((IAsyncResult e) =>
{
Socket socket = (Socket)e.AsyncState;
SocketBase.StateObject stateObject = new SocketBase.StateObject();
stateObject.workSocket = socket;
socket.BeginReceive(stateObject.buffer, 0, 256, SocketFlags.None, new AsyncCallback(this.ReadCallback), (object)stateObject);
}), sender);
sender = RetrieveSocket(); //Socketreset
Thread.Sleep(100);
}
catch /*(Exception e)*/
{
//--
}
}
Server listener
public void StartListening()
{
listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
try
{
listener.Bind(localEndPoint);
listener.Listen(System.Int32.MaxValue);
while (true)
{
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
}
catch (Exception e)
{
//--
}
}
public void AcceptCallback(...);
public void ReadCallback(...);
Socket send
private void Send(Socket handler, String data)
{
Socket t = RetrieveSocket(((IPEndPoint)handler.RemoteEndPoint).Address);
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.UTF8.GetBytes(data);
// Begin sending the data to the remote device.
t.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), t);
}
Socket send all data part (answer to getdata-request | socToHandle should be the socket of the previous connection of the getdata-request)
private void SendAllData(Socket socToHandle, string PakContent)
{
#region IsThereADatetime? //Resolve a given datetime
#region GiveClientNumberOfPackets //Send the client info about how much he has to receive (See line below)
Send(socToHandle, "ALERT#TASKCOUNT;OPT-" + GetBestDate(dateStart) + EndSocket);
#region #SendResouces
#region #SendGroups
#region #SendTasks
}
Looking through my old code I have one idea =>
Could I send everything over the same connection by changing:
Socket t = RetrieveSocket(((IPEndPoint)handler.RemoteEndPoint).Address);
(which creates a new connection) to something that uses the same connection?
If that would work, how can I do that?
And would the listener part of the client still receive single packets?
Servers and their environment are configured to handle incoming requests properly. Clients are usually behind a router, which by default make them unable to receive incoming connections from outside their network (a good thing).
To enable incoming connections, you could configure your router to forward all requests for a certain port number to your machine. No one else on your network would be able to run the client then, though.
This is why in a typical multiple clients-single server environment, the client makes all the connections, and only the server requires any changes to the network landscape.
I don't know why you chose to connect to the clients from the server side, but I would strongly advise against this - any cheap solution that uses this mechanism may turn out to be very expensive in the end.
I trying to write a TFTP client for a class project.
Using the UdpClient class I can successfully request data from the server but the returned packet never reaches my code.
My firewall is turned off.
I can observe the returned packet in wireshark but UdpClient.Receive blocks indefinitely.
mUdpClient is initialized like this in the constructor: mUdpClient = new UdpClient();
mUdpClient is connected like this
public void connect(String host, int port) {
mServerAddress = System.Net.Dns.GetHostAddresses(host)[0];
var endPoint = new IPEndPoint(mServerAddress, port);
mUdpClient.Connect(endPoint);
}
After the connect I send my request which is successful (as observed in wireshark)
This is what my receive code looks like
private void receiveResponse() {
var newEndpoint = new IPEndPoint(IPAddress.Any, 0);
byte[] response = mUdpClient.Receive(ref newEndpoint);
Console.Out.WriteLine(response);
}
This has been tested on my Surface Pro and a Windows 8.1 VirtualBox VM running under Debian.
Note that since you are using the Connect() method on your UDP socket, you will only see datagrams actually sent from that IPEndPoint. If your remote host for some reason uses a different IPEndPoint to send data back to you, you won't see it. So maybe try not using the default host feature (i.e. don't call Connect...just provide the remote IPEndPoint on each Send() call).
I'm new to C# and I was wondering if it's possible to have a mechanism to check authorization similar to how a TCP client sends a decrypted password in its handshake packet. If not, how can I prevent unauthorized clients from connecting to my TCP server?
The code below shows where I accept each client and keep them in a TCPClientObject Array for further use later:
private void startTcpClientAccept()
{
while (true)
{
TCPClientObject temp = new TCPClientObject();
temp.setIndex(availableIndexes.Dequeue());
temp.setClient(server.AcceptTcpClient());
//I need the check mecanism here. before receiving any messages
clientList[temp.getIndex()] = temp;
Console.WriteLine("GSM Client is accepted");
}
}
Basically, the problem is anyone can connect to server and this may create some security problems further.