开发者

JoCaml : problems with remote connection

开发者 https://www.devze.com 2023-02-14 21:54 出处:网络
(Probably just knowledge of the Unix library is enough to answer this, so please read on if you don\'t know JoCaml.)

(Probably just knowledge of the Unix library is enough to answer this, so please read on if you don't know JoCaml.)

I have two programs in JoCaml. A server, ready to return the square of a number on port 12345

(* p.ml *)
def f (x) =
        print_string ("["^string_of_int(x)^"] "); flush stdout;
        reply x*x to f
in Join.Ns.register Join.Ns.here "square" f
;;
let wait =
        def x () & y () = reply to x
        in x
let main =
        Join.Site.listen (Unix.ADDR_INET (Join.Site.get_local_addr(), 12345));
        wait()

and a client, ready to use the square function of the server

(* q.ml *)
let server =
        let server_addr = Unix.gethostbyname "192.168.0.10" in
        Join.Site.there (Unix.ADDR_INET(server_addr.Unix.h_addr_list.(0),12345))
let ns = Join.Ns.of_site server
let sqr = (Join.Ns.lookup ns "square": int -> int)
let _ = Printf.printf "%d\n" (sqr 3)

This all works fine if the two programs are running on the same machine. But my goal is to put them in two different machines. So the IP above should become some other public IP. Since I only have one machine to test this, I decided to run the two programs on that machine and write, instead of the 192.168.0.10 above, the public IP of my machine. Unfortunately, it doesn't work, connection times out.

Any ideas?

[EDITED]

More details on the problem

The code I wrote above is an example I took from the JoCaml manual as it was an analogous and simplified version of my own piece of code where the question came up. The program I'm writing aims to create a P2P network of JoCaml runtimes which all make private computations, and store their results locally, relying on data stored in other peers of the network. So, I want to have a set of peers all running something "similar" to q.ml, in that they need to connect to other machines and fetch the information they need from them.

Each peer needs to keep 开发者_运维技巧a list of its peers. You can then query the network for some value in a simple way. Each peer will check if it knows that value: if so returns it, if not it asks its peers (and so on, recursively). The P2P architecture is really good for my purposes. (The centralised topology suggested by Gilles won't work for my particular problem due to the performance and reliability issues mentioned in his answer.) I've introduced a special bootstrap peer which all code knows about and to which any new peer will first connect to get access to the network. Once the new peer is authenticated by the bootstrap peer, it should join the network and become a first-class peer on its own (and may ignore the bootstrap peer from then on). These peers will all communicate directly between them (1-1) so there needs to be a way for each arbitrary pair of peers to establish a connection between them. Also, since I'd like anyone with appropriate credentials to be able to join this network, regardless of their network skills, I can't have a solution where people need to configure their router to join the P2P network. They should just run the software out of the box.

My requirements are then:

  1. P2P network of peers on the internet (so, 1-1 connection between any two nodes)
  2. peers may be behind opaque routers
  3. no local router configuration
  4. special bootstrap peer to which you first connect and authenticate

What I currently have works well if we don't require 2. Any suggestions to solve the initial problem but in this P2P context?

(Note that the P2P framework is just a means to an end. Yes, I'd like to have something that works well, but I don't intend to develop the ultimate super-general P2P framework for JoCaml. I'm looking to write a simple thing which simply does the job.)


(I think your problem is with IP network topology and not with programming per se, but you need to understand this background to program in JoCaml.)

A long time ago, every computer on the Internet had an IP address, and you could talk to that computer if you knew its IP address. (Routers have one IP address per interface, but this is only a concern to network administrators.) Ah, for the simplicity of the good old days.

Now things have become more complicated. It is common for computers on an intranet to have an address that's only valid on that intranet, a so-called private address. 192.168.0.10 is such a private address. You can only talk to a computer with a private address from within that intranet. When the computer needs to make connections to the outside, network address translation (NAT) is used to make a particular connection work. NAT gives the intranet computer a public address, but only valid for a particular connection.

I suspect the network topology you're confronted with looks like this, where A is your computer, C is the other computer you eventually to work with, R is your home or office router, and 1.2.3.4 is what you call the public IP of your machine (actually, of your network):

C [5.6.7.8] ←———→ [1.2.3.4] R [192.168.0.1] ←———→ [192.168.0.10] A

In this situation, C can't talk to A using the 192.168.0.10 address, because that address is only meaningful on the intranet. If C can talk to A at all, it must use 1.2.3.4, and R must be configured to relay packets addressed to 1.2.3.4 to A (in typical configurations, R will only do this on certain TCP or UDP ports if at all). But A can't talk to itself using 1.2.3.4 as an address: coming from inside, this is likely to reach R only, if at all.

This problem — that the participants in a network don't have a globally visible and unique address — is possible but annoying to solve in theory, and possible but annoying to solve in practice. As far as I know, Jocaml's library uses IP addresses and port numbers to uniquely and globally identify the nodes in a distributed program. .

Given the complexities of modern network topologies, it often helps to divide the problem in two parts: getting the machines to talk to each other, and actually running a distributed program. The second part is what you're doing when you program in JoCaml. For the first part, ssh is the tool of choice. Decide on one machine or one network area (the Internet or an intranet) as the domain where your program will run, and connect every machine outside that domain to a machine in the domain with an SSH tunnel. This approach is not suitable for all use cases: communication between two machines outside the domain will go through the domain, and that can be a performance and reliability problem. To go beyond this, you'll need to either configure your network so that every participant has an address that's visible to every other participant (which you may or may not be able to do, depending on what you're allowed to do on the routers involved); or implement a non-global address model for JoCaml (which would be interesting and useful, but a lot of effort).


By using

Unix.ADDR_INET(server_addr.Unix.h_addr_list.(0), 12345)

you tell the system you want the port to be bound to the local loopback interface only. This is a special virtual network device that can be used for fast local communication.

Rather use

Unix.ADDR_INET (Unix.inet_addr_of_string "0.0.0.0", 12345)

to listen on any network interface of your machine. This way your server will accept connections from the real network interfaces, too.

0

精彩评论

暂无评论...
验证码 换一张
取 消