SANAT
GÜZELLİK & SAĞLIK
ZANAAT
KÜLTÜR & TARİH
EĞLENCE
ÇEVRE
YİYECEK & İÇECEK
TERS MÜHENDİSLİK
BİLİMLER
SPOR
TEKNOLOJİ
GİYİLEBİLİR ÜRÜNLER
The ARPANET IMP
Pixel

Oluşturan

Pixel

30. Ağustos 2026FI
28
0
0
0
0

The ARPANET IMP

Packet switching was an argument until BBN built the box. The Interface Message Processor was a ruggedised Honeywell DDP-516 with twelve thousand words of core memory, weighing about four hundred kilograms, and its entire purpose was to be the part of the network that the university's computer did not have to understand. That division is the invention, more than any algorithm in it. Each site's host spoke to its IMP over a simple local interface specified in BBN Report 1822, and the IMP dealt with everything else: chopping messages into packets of about a thousand bits, checksumming them, sending them to a neighbour, waiting for that neighbour's acknowledgement, retransmitting when it did not come, and choosing which neighbour to use in the first place. A host with a different word length, a different character set and a different operating system needed to know none of it. The first IMP went to UCLA on the thirtieth of August 1969. The second went to SRI. On the twenty-ninth of October they tried to send the word LOGIN from one to the other; SRI received L, then O, and then crashed. By December there were four nodes, joined by fifty-kilobit leased lines, and no IMP knew the shape of the network — each kept a table of estimated delays, told its neighbours, and believed whichever offered the lowest total. FULLY BUILDABLE, and this is the one to actually build. Three microcontrollers in a chain, where the two ends have no direct link, so every packet between them must be stored, checked and forwarded by the middle one. That is an IMP's whole job, and seeing it work is different from reading about it.
İleri
5 hours

Talimatlar

1

Build the three-node network

Flash the same sketch on three boards, changing MY_ADDR to 1, 2 and 3. Wire them as a chain — node 1 to node 2, node 2 to node 3 — and note that 1 and 3 are NOT connected. Open all three serial monitors. Node 1 sends to node 3 every two seconds; node 2 prints that it is relaying; node 3 prints DELIVERED. Nothing in node 1's code knows how node 3 is reached. Now do the experiment that matters. Briefly short the link between 2 and 3 with a jumper to corrupt a packet in flight. Node 2 prints CRC FAIL and DROPS it — it does not forward what it could not verify. That single decision is why a store-and-forward network can be built out of unreliable links at all: every hop refuses to launder corruption onward, so errors stop where they happen instead of arriving at the far end disguised as data.
imp_node.inocpp
// A three-node store-and-forward network, which is what an IMP actually is.
//
// Flash the SAME sketch on three boards and set MY_ADDR to 1, 2 and 3. Wire them in a
// chain: node 1 TX -> node 2 RX, node 2 TX -> node 3 RX, and the return path likewise.
// Node 1 and node 3 have no direct link, so every packet between them must be RELAYED --
// and node 2 has to store the whole packet, verify it, and forward it.
//
// This is the IMP's whole job. What the hosts see is a network; what node 2 does is
// receive, check, look up, and re-transmit.
//
// PACKET: [SOF][dst][src][id][len][payload...][crc_hi][crc_lo]

const uint8_t MY_ADDR = 1;         // <-- 1, 2 or 3
const uint8_t SOF     = 0x7E;

const int PIN_TX_LEFT  = 17, PIN_RX_LEFT  = 16;   // toward the lower-numbered node
const int PIN_TX_RIGHT = 26, PIN_RX_RIGHT = 25;   // toward the higher-numbered node

HardwareSerial Left(1), Right(2);

uint16_t crc16(const uint8_t *d, int n) {          // blueprint 2, in eight lines
  uint16_t reg = 0xFFFF;
  for (int i = 0; i < n; i++) {
    reg ^= (uint16_t)d[i] << 8;
    for (int b = 0; b < 8; b++)
      reg = (reg & 0x8000) ? (reg << 1) ^ 0x1021 : reg << 1;
  }
  return reg;
}

void sendOn(HardwareSerial &port, uint8_t dst, uint8_t src, uint8_t id,
            const uint8_t *payload, uint8_t len) {
  uint8_t buf[64];
  int n = 0;
  buf[n++] = dst; buf[n++] = src; buf[n++] = id; buf[n++] = len;
  for (int i = 0; i < len; i++) buf[n++] = payload[i];
  uint16_t c = crc16(buf, n);
  port.write(SOF);
  port.write(buf, n);
  port.write(c >> 8); port.write(c & 0xFF);
}

// Receive one whole packet, or return false. STORE first, forward later: an IMP must
// have the entire packet before it can check it, and it must check it before it repeats
// it -- otherwise it launders corruption onward as if it were good.
bool recvFrom(HardwareSerial &port, uint8_t *dst, uint8_t *src, uint8_t *id,
              uint8_t *payload, uint8_t *len, unsigned long timeout_ms) {
  unsigned long t0 = millis();
  while (port.available() < 1) if (millis() - t0 > timeout_ms) return false;
  if (port.read() != SOF) return false;

  uint8_t hdr[4];
  for (int i = 0; i < 4; i++) {
    while (!port.available()) if (millis() - t0 > timeout_ms) return false;
    hdr[i] = port.read();
  }
  *dst = hdr[0]; *src = hdr[1]; *id = hdr[2]; *len = hdr[3];
  if (*len > 48) return false;

  uint8_t buf[64];
  int n = 0;
  for (int i = 0; i < 4; i++) buf[n++] = hdr[i];
  for (int i = 0; i < *len + 2; i++) {
    while (!port.available()) if (millis() - t0 > timeout_ms) return false;
    buf[n++] = port.read();
  }
  uint16_t got = (buf[n-2] << 8) | buf[n-1];
  if (crc16(buf, n - 2) != got) {
    Serial.println("# CRC FAIL -- dropped, NOT forwarded");
    return false;                                  // an IMP drops rather than propagates
  }
  for (int i = 0; i < *len; i++) payload[i] = buf[4 + i];
  return true;
}

void relayOrDeliver(uint8_t dst, uint8_t src, uint8_t id, uint8_t *pl, uint8_t len) {
  if (dst == MY_ADDR) {
    Serial.printf("DELIVERED from %u id %u: ", src, id);
    for (int i = 0; i < len; i++) Serial.write(pl[i]);
    Serial.println();
  } else {
    // The whole routing table, for a chain: go toward the destination.
    Serial.printf("# relaying %u->%u id %u\n", src, dst, id);
    if (dst > MY_ADDR) sendOn(Right, dst, src, id, pl, len);
    else               sendOn(Left,  dst, src, id, pl, len);
  }
}

void setup() {
  Serial.begin(115200);
  delay(300);
  Left.begin(9600, SERIAL_8N1, PIN_RX_LEFT, PIN_TX_LEFT);
  Right.begin(9600, SERIAL_8N1, PIN_RX_RIGHT, PIN_TX_RIGHT);
  Serial.printf("# IMP node %u ready\n", MY_ADDR);
}

uint8_t nextId = 0;

void loop() {
  uint8_t dst, src, id, pl[48], len;
  if (recvFrom(Left,  &dst, &src, &id, pl, &len, 5)) relayOrDeliver(dst, src, id, pl, len);
  if (recvFrom(Right, &dst, &src, &id, pl, &len, 5)) relayOrDeliver(dst, src, id, pl, len);

  // Node 1 sends to node 3 every two seconds. It has no link to node 3.
  static unsigned long last = 0;
  if (MY_ADDR == 1 && millis() - last > 2000) {
    last = millis();
    const char *msg = "LO";                        // what they actually got, 29 Oct 1969
    sendOn(Right, 3, MY_ADDR, nextId++, (const uint8_t*)msg, strlen(msg));
    Serial.printf("# sent to 3, id %u\n", nextId - 1);
  }
}

Bu adım için malzemeler:

Jumper Wire SetJumper Wire Set1 adet
Resistor KitResistor Kit1 adet

Gerekli aletler:

ESP32 Development BoardESP32 Development Board
Breadboard - ClassicBreadboard - Classic
Desktop ComputerDesktop Computer
Digital OscilloscopeDigital Oscilloscope
2

Watch the routing converge and then break

Extend the sketch so each node keeps a one-line table — for each destination, which neighbour and how many hops — and broadcasts it to both neighbours once a second. On receiving a neighbour's table, take any route that is cheaper than your own, plus one. Boot all three at once with the tables empty and watch them fill. Node 1 learns about node 3 only because node 2 tells it. Nobody is in charge and there is no map. Then unplug the link between 2 and 3 while it runs. Watch what node 1 believes. It will keep advertising a route to node 3 for several seconds, because its information came from node 2 and node 2 has not yet convinced it otherwise. That lag is not a bug in your code. It is the counting-to-infinity problem, and the notebook shows why it is inherent to asking your neighbours instead of knowing the map.

Gerekli aletler:

ESP32 Development BoardESP32 Development Board
Desktop ComputerDesktop Computer
StopwatchStopwatch
3

Delay, convergence, and counting to infinity

Jupyter defteri yükleniyor…

Gerekli aletler:

Desktop ComputerDesktop Computer
4

Compendium: the box that let hosts stay ignorant

THE INTERFACE WAS THE INVENTION. BBN Report 1822 defined a deliberately dumb link between host and IMP: hand over a message of up to 8095 bits with a destination number, and eventually get back a Request For Next Message meaning the far IMP has it. Everything else — packetisation, checksums, hop-by-hop acknowledgement, retransmission, routing, reassembly — happened inside the subnet. A PDP-10, a Sigma 7 and an IBM 360 with three different word lengths and three different character sets could join a network without agreeing on anything except that interface. Every later network kept the idea and moved the line: what an IMP did in hardware, IP and TCP later did in software on the host. WHAT IT PROMISED, AND WHAT IT DID NOT. The IMP subnet promised to deliver messages between hosts, in order, or to say it could not. It did NOT promise a delivery time, and it could not survive a partition. It also could not talk to a network that was not the ARPANET, because addresses were IMP numbers on one network. That last limit is exactly what the datagram of blueprint 9 removes, and the word internetwork is what it removes it for.

Malzemeler

2

Gerekli Aletler

5

CC0 Kamu Malı

Bu plan CC0 lisansıyla yayınlanmıştır. İzin almadan kopyalayabilir, değiştirebilir, dağıtabilir ve herhangi bir amaçla kullanabilirsiniz.

Planı üzerinden ürün satın alarak Maker'ı destekleyin, böylece Maker Komisyonu Satıcılar tarafından belirlenen komisyonu kazanırlar veya bu Planın yeni bir versiyonunu oluşturun ve gelir paylaşımı için kendi Planınıza bağlantı olarak ekleyin.

Tartışma

(0)

Giriş yapın tartışmaya katılmak için

Yorumlar yükleniyor...