I am trying to build a WCF client for a Java Socket server which talks on a custom XML messages. I have created my own custom binding with MessageEncoder and netTCP transport.
Now what I have seen happen is
on the first call to the server, server accepts the connection. However the server then waits for a specific XML packet. This is built into the method interface from client. WCF does not send the XML packet.
Later WCF reports a timeout exception and the channel is faulted.
Will WCF netTCP transport work only with a WCF TCP Server?
Code:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName = "IUserManager", SessionMode=System.ServiceModel.SessionMode.Required)]
public interface IUserManager
{
[System.ServiceModel.OperationContract]
bool SendMessage(string strMessage);
[System.ServiceModel.OperationContract(IsInitiating = true, IsOneWay=true)]
void SendMessageOneWay(string strMessage);
}
I have created a SendMessageOneWay just to initiate the Socket connection. This did not work as well. As I need to reuse the socket, I have set Session.Required.
Please help
The WCF netTCP transport uses a custom TCP-based protocol; it is not a general purpose raw-TCP socket adapter.
Sounds like you will need to create your own custom transport channel. I created a list of resources on writing WCF channels a while ago (might be a bit out of date, but it should still be useful for getting started)
Yes wcf using .net framing protocol which is not interoperable.
http://blogs.msdn.com/b/drnick/archive/2009/01/19/message-framing-part-1.aspx
Related
Intro
My code can process all bytes that are sent to a server and decide whether or not to let them go through and eventually send responses. I would like to use this to use the server as web server, web socket server and tcp server in one.
Although my code is written for Minecraft, I am not asking this on a Minecraft forum because answering this question doesn't require any prior knowledge about Minecraft or its codebase.
All you need to know about Minecraft
Minecraft is a Java game that can be played online. When it is being played online, there is a server that opens a ServerSocket and all players have their own client that opens a Socket that will communicate with the ServerSocket of the server.
Anyone can create a Minecraft server and install server-side modifications on their server (for those who know Minecraft, these are usually called plug-ins). My application is such a server-side modification. Most Minecraft servers are being hosted by Minecraft host companies. The owners of the servers have some kind of access to the part of the host computer that manages the server files.
Goal
The goal of my modification is to let the Minecraft server serve more clients than just the Minecraft clients. I would like the same server to also work as web server (for http and https requests) as well as (secure) web socket server and tcp server.
Why no multiple server sockets
The most common solution would be to just create a ServerSocket for the other server types and assign a different port to all of them. However, that is not an option in my case. Most hosts forbid you to open other ports or ask extra money for it. So I need to do it all with just the Minecraft ServerSocket.
What I achieved so far
So far, I have managed to let all bytes that are sent to the minecraft server first go through my code. My code can choose whether or not to let the bytes continue to the Minecraft server code. It can also send responses on its own without the need to inform the Minecraft server code at all.
In principle, what I have managed to do is sufficient to accomplish my goal, but I would like some help with how to continue. I will explain below what I have and have not accomplished so far.
The first byte that is sent by a Minecraft client to the server is always the same, namely 16. This is great because it allows me to easily distinguish Minecraft clients from web browsers and tcp clients.
HTTP requests and websocket connections always start with the same byte, namely 71. HTTPS and secure websockets always start with the byte 22. The TCP connections I was talking about will be sent by my own applications, so I can choose exactly what bytes they will send and I can simply program my modification to respond to that.
I managed to distinguish http requests and websocket connections by their connection property. Http requests always send 'Connection: keep-alive' while websocket connections always send 'Connection: upgrade'. (Although some browsers do the k, a and u in uppercase and others do not.)
Handling normal http requests wasn't very hard to do. Handling TCP connections won't be hard either because I will control everything. But I have issues with the remaining connection types:
Problems I need help with
The web socket protocol is quite large and I would prefer not to handle it completely with only my code. (I tried this before, but I kept having problems with the parts that were rarely used and thus not tested.) So I would like to use some library that allows me to only worry about the payload rather than the entire protocol. Unfortunately, web socket libraries generally want to create the ServerSocket, which is not possible in my case. So does anyone have advice on what to do here?
I haven't found any info on how to read https requests properly. Could someone tell me where to look for the details of this protocol or provide a nice link?
For secure web sockets, I will face the same problems as with the 'normal' web socket connections after I find out how to read the requests.
Code
All my code so far can be found at https://github.com/knokko/Multi-Purpose-Server. The most interesting part is probably the part where my code gets the opportunity to process all bytes before they arrive at the Minecraft code, that code is shown below.
Short question(s)
For those who didn't understand exactly what my question (you could see it as 2 questions that are strongly related) is:
-How I should read https requests and secure web socket handshakes?
-Does anyone know a library that can handle web socket input that doesn't require to create the ServerSocket itself?
// This channel handler will be registered for every connection client that will
// inspect
// any message before it reaches the Minecraft code.
pipeline.addFirst("multipurpose_handler_inspector", new ChannelInboundHandlerAdapter() {
private boolean deactivated;
private ChannelListener listener;
#Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//super.channelRead will send the content to the minecraft code
try {
if (!deactivated) {
ByteBuf message = (ByteBuf) msg;
if (listener != null) {
listener.read(ctx, message);
} else {
byte firstByte = message.getByte(0);
// All Minecraft connections start with the byte 16
if (firstByte == 16) {
deactivated = true;
super.channelRead(ctx, msg);
}
// All insecure web connections start with the byte 71
else if (firstByte == 71) {
byte[] data = new byte[message.readableBytes()];
message.getBytes(0, data);
WebHandler.Type type = WebHandler.determineConnectionType(data);
if (type == WebHandler.Type.HTTP) {
listener = new HTTPListener();
listener.readInitial(ctx, message);
} else if (type == WebHandler.Type.WEBSOCKET) {
// TODO Find a nice way to handle web socket connections
listener = new WebSocketListener();
listener.readInitial(ctx, message);
} else {
deactivated = true;
super.channelRead(ctx, msg);
}
}
// All secure web connections start with the byte 22
else if (firstByte == 22) {
// TODO implement the secure web protocols and find a way to read this stuff
// and find the difference
System.out.println(
"We are dealing with a secure websocket or https connection");
byte[] data = new byte[message.readableBytes()];
message.getBytes(0, data);
System.out.println(new String(data));
}
// My applications
else if (firstByte == 31) {
listener = new TCPListener();
listener.readInitial(ctx, message);
} else {
System.out.println("Unknown connection type");
deactivated = true;
super.channelRead(ctx, msg);
}
}
} else {
super.channelRead(ctx, msg);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
If you can ALWAYS identify the Minecraft traffic, your best bet might be to run an apache/httpd and/or tomcat server on the same box and forward all non-Minecraft traffic to it. If you do this, the HTTPS stuff might just be a matter of correctly configuring the http server for https traffic.
You may have to configure your code as an http proxy--in fact (Just thought of this) you might want to go out and look for an open source http proxy and just tweak it with your code to extract Minecraft traffic and forward it before doing the rest of the proxy stuff.
I wouldn't do the HTTPs stuff from scratch, it's not terribly difficult but I'd call it non-trivial.
Oh and if your problem is "differentiating Minecraft HTTPS traffic from other HTTPS connections on the same port" I can't help except to say that this might be a good subject for your question :)
I have a REST endpoint and I want to access it using UDP for example Java Datagram. I know its not a best practice to try even but my recent project I have some hardware limitations. Hardware can make UDP calls only and my existing services are over REST i.e. HTTP/HTTPS.
I am looking for any way I can reuse my existing services. I have tried following code but received UnknownHostException.
public class UDPClinet {
public static void main(String[] args) {
String hostname = "https://jsonplaceholder.typicode.com/posts/1";
int port = 80;
try {
InetAddress address = InetAddress.getByName(hostname);
DatagramSocket socket = new DatagramSocket();
while (true) {
DatagramPacket request = new DatagramPacket(new byte[1], 1, address, port);
socket.send(request);
byte[] buffer = new byte[512];
DatagramPacket response = new DatagramPacket(buffer, buffer.length);
socket.receive(response);
String quote = new String(buffer, 0, response.getLength());
System.out.println(quote);
System.out.println();
Thread.sleep(10000);
}
} catch (SocketTimeoutException ex) {
System.out.println("Timeout error: " + ex.getMessage());
ex.printStackTrace();
} catch (IOException ex) {
System.out.println("Client error: " + ex.getMessage());
ex.printStackTrace();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
Is it possible to implement a RESTful service that can be called via UDP.
Yes. (See below)
Can you call your existing RESTful service via UDP?
Probably no. And certainly not without a lot of work.
Typical RESTful services are in fact implemented using HTTP or HTTPS over TCP/IP connections. It is not possible to talk directly to an TCP-based service using UDP. The IP-level packets will have the wrong protocol family and the service's OS won't route them to the service.
However, it is possible (technically speaking) to implement RESTful services over any transport that is capable of sending messages. REST principles are agnostic of the transport protocol.
The problem will be finding a service framework that support RESTful UDP and (conventional) RESTful HTTP at the same time.
There are a couple of other practical problems:
UDP is unreliable, and this is exacerbated if you send datagrams that won't fit into a packet with the default MTU (1500 bytes). So if you want to implement a RESTful service over UDP, you will need to play close attention to the size of request and response payloads.
HTTPS uses TLS so that the client is able to validate the server's authenticity and then send data encrypted. TLS over UDP is possible (it is called DTLS) and supported by JCSE, but using it in a typical RESTful / HTTP framework may be challenging.
If you want to pursue this, look for a RESTful framework that implements CoAP (Constrained Application Protocol - RFC 7252) and DTLS.
You may have a look at available CoAP implementations, see coap.technology for an overview. Though I'm a committer of Eclipse/Californium, a CoAP/DTLS implementation in java, I would recommend to try that out.
CoAP also defines Cross Proxies to HTTP. There is one example available in the google cloud tutorials. It's using a older Californium version as base. Californium itself has an update proxy exmaple (but not out of the box usable for the google cloud), see Californium - Proxy2.
Yes, there's a internet standard now for REST over UDP, it's goes by the name the Constrained Application Protocoal - CoAP. CoApp is defined in a series of internet standards starting with RFC 7252.
CoAP addresses concerns raised in earlier answers to this question, including using retransmissions over UDP to make it reliable, and providing for security using DTLS.
CoAP has been designed to work on microcontrollers with as low as 10 KiB of RAM and 100 KiB of code space (RFC 7228). Furthermore it adds very little overhead to the UDP packets, using a binary fixed header of 4 bytes, and variable length options (like optional HTTP headers)
I'm writing a game server in Java, and I'm using Netty 3.6.2. The game servers should accept no HTTP requests, as they simply handle game client data (which is purely bytes over TCP). When I load http://server-ip:game-servers-port in Chrome, I download a file with the game's handshake packet (which should not happen).
I bind to the game server's port like so:
ChannelFactory factory = new NioServerSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool());
clientAcceptor = new ServerBootstrap(factory);
clientAcceptor.setOption("child.tcpNoDelay", true);
clientAcceptor.setOption("child.keepAlive", false);
clientAcceptor.setPipelineFactory(() -> Channels.pipeline(new PacketDecoder(), new ClientHandler()));
clientAcceptor.bind(new InetSocketAddress(Configurations.CHANNEL_GAME_PORT));
And I process requests in a SimpleChannelHandler, like so
#Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
// Encryption key code.
Packets.sendHello(ctx.getChannel(), ivRecv, ivSend);
ctx.getChannel().setAttachment(client);
}
How can I go about deciphering if an incoming request is using the HTTP protocol?
Edit: I should also say, it should also block any FTP, WebSocket, etc. protocol (essentially anything that isn't the game's protocol) on channel connect.
You can't expect to be able to disable HTTP requests if the first thing you do with an accepted connection is to send something.
Have the client do the first send in the handshake. Have the server start by doing a receive, and if it isn't the correct initial handshake packet, close the connection.
I have a java server aplication which comunicate with multiple clients via SocketChannel. On this channel, client sends a request and server sends an answer. Now I want add feature that server can sends file to the client. I don't want send it via the socket whith I am using for comunication so is good idea to have more sockets between one client and one server? If yes how to handle them? Have I use something like this?
SocketChannel socket = serverSocket.accept()
if(!addressSet.contains(socket.address)) {
it is comunicate socket
}
else {
it is date transfer socket
}
or is there some better way?
Create a new ServerSocket on a random port once you accept a client connection, then tell him that port number. He should then connect to that as the data connection. Then,have the server accept one connection from it, which better be from him, then close that ServerSocket. It's not foolproof but it's reasonably strong.
Yes there is a better way.
Use ServerSocketChannel and the method public abstract SocketChannel accept() throws IOException
Here's what I'm trying to do- A server sends out "Alive message to all the PCs on the network and the PCs which are up and running, respond to the call by sending their IP.
I'm looking at a lightweight piece of coding as this will form a small bit of my application.
I've looked at Jini and other services but find that I may not need even half of their features(except for the network discovery)
Is it ok if I:
1. Use a for loop where a server opens a socket, checks(using a for loop) if all the IPs x.x.x.x are reachable by sending an "Alive" message.
2. On receiving the "alive" message at the client at the specific socket, the client replies with its IP.
Is this method OK? Do you think I could do it in a better way?
Thanks!
I had a similar problem a long time ago and I resolved it as follows:
The server broadcasts a UDP packet on the network to 255.255.255.255
All reachable clients will respond with a UDP packet that include their IP and any other information you wish to send.
The packet I personally used looks like
public class UDPDiscoveryPacket{
public final long sendingTime;
public final String clientIP;
public UDPDiscoveryPacket(long sendingTime, String clientIP){
this.sendingTime = sendingTime;
this.clientIP = clientIP;
}
}