rpc network fses
play

RPC / Network FSes 1 last time names and addresses IPv4, IPV6 - PowerPoint PPT Presentation

RPC / Network FSes 1 last time names and addresses IPv4, IPV6 addresses, routers tables DNS: hierarchical database POSIX socket API socket bind/listen/accept getaddrinfo 2 FTP protocol (simplifjed) 230 User logged in


  1. GRPC IDL example rpc ListDirectory(ListDirArgs) returns (DirectoryList) {} rule: arguments/return value always a message will become method of C++ class allows changing fjeld names, adding new fjelds, etc. numbers are used in byte-format of messages fjelds are numbered (can have more than 1 fjeld) part of protocol bufgers (usable without RPC) with accessors + marshalling/demarshalling functions messages: turn into C++ classes } rpc MakeDirectory(MakeDirArgs) returns (Empty) {} message MakeDirArgs { required string path = 1; } service Directories { } repeated DirectoryEntry entries = 1; message DirectoryList { } optional bool is_directory = 2; required string name = 1; message DirectoryEntry { message ListDirArgs { required string path = 1; } 14

  2. RPC server implementation (method 1) class DirectoriesImpl : public Directories::Service { public : return Status(StatusCode::UNKNOWN, strerror(errno)); } return Status::OK; } ... }; 15 Status MakeDirectory(ServerContext *context, const MakeDirArgs* args, Empty *result) { std::cout << "MakeDirectory(" << args − >name() << ")\n"; if ( − 1 == mkdir(args − >path().c_str()) {

  3. RPC server implementation (method 1) class DirectoriesImpl : public Directories::Service { public : return Status(StatusCode::UNKNOWN, strerror(errno)); } return Status::OK; } ... }; 15 Status MakeDirectory(ServerContext *context, const MakeDirArgs* args, Empty *result) { std::cout << "MakeDirectory(" << args − >name() << ")\n"; if ( − 1 == mkdir(args − >path().c_str()) {

  4. RPC server implementation (method 1) class DirectoriesImpl : public Directories::Service { public : return Status(StatusCode::UNKNOWN, strerror(errno)); } return Status::OK; } ... }; 15 Status MakeDirectory(ServerContext *context, const MakeDirArgs* args, Empty *result) { std::cout << "MakeDirectory(" << args − >name() << ")\n"; if ( − 1 == mkdir(args − >path().c_str()) {

  5. RPC server implementation (method 1) class DirectoriesImpl : public Directories::Service { public : return Status(StatusCode::UNKNOWN, strerror(errno)); } return Status::OK; } ... }; 15 Status MakeDirectory(ServerContext *context, const MakeDirArgs* args, Empty *result) { std::cout << "MakeDirectory(" << args − >name() << ")\n"; if ( − 1 == mkdir(args − >path().c_str()) {

  6. RPC server implementation (method 2) class DirectoriesImpl : public Directories::Service { public : ... for (...) { } return Status::OK; } ... }; 16 Status ListDirectory(ServerContext *context, const ListDirArgs* args, DirectoryList *result) { result − >add_entry(...);

  7. RPC server implementation (method 2) class DirectoriesImpl : public Directories::Service { public : ... for (...) { } return Status::OK; } ... }; 16 Status ListDirectory(ServerContext *context, const ListDirArgs* args, DirectoryList *result) { result − >add_entry(...);

  8. RPC server implementation (method 2) class DirectoriesImpl : public Directories::Service { public : ... for (...) { } return Status::OK; } ... }; 16 Status ListDirectory(ServerContext *context, const ListDirArgs* args, DirectoryList *result) { result − >add_entry(...);

  9. RPC server implementation (method 2) class DirectoriesImpl : public Directories::Service { public : ... for (...) { } return Status::OK; } ... }; 16 Status ListDirectory(ServerContext *context, const ListDirArgs* args, DirectoryList *result) { result − >add_entry(...);

  10. RPC server implementation (starting) DirectoriesImpl service; ServerBuilder builder; builder.AddListeningPort("127.0.0.1:43534", grpc::InsecureServerCredentials()); builder.RegisterService(&service); unique_ptr<Server> server = builder.BuildAndStart(); 17 server − >Wait();

  11. RPC server implementation (starting) DirectoriesImpl service; ServerBuilder builder; builder.AddListeningPort("127.0.0.1:43534", grpc::InsecureServerCredentials()); builder.RegisterService(&service); unique_ptr<Server> server = builder.BuildAndStart(); 17 server − >Wait();

  12. RPC server implementation (starting) DirectoriesImpl service; ServerBuilder builder; builder.AddListeningPort("127.0.0.1:43534", grpc::InsecureServerCredentials()); builder.RegisterService(&service); unique_ptr<Server> server = builder.BuildAndStart(); 17 server − >Wait();

  13. RPC server implementation (starting) DirectoriesImpl service; ServerBuilder builder; builder.AddListeningPort("127.0.0.1:43534", grpc::InsecureServerCredentials()); builder.RegisterService(&service); 17 unique_ptr<Server> server = builder.BuildAndStart(); server − >Wait();

  14. RPC server implementation (starting) DirectoriesImpl service; ServerBuilder builder; builder.AddListeningPort("127.0.0.1:43534", grpc::InsecureServerCredentials()); builder.RegisterService(&service); unique_ptr<Server> server = builder.BuildAndStart(); 17 server − >Wait();

  15. RPC server implementation (starting) DirectoriesImpl service; ServerBuilder builder; builder.AddListeningPort("127.0.0.1:43534", grpc::InsecureServerCredentials()); builder.RegisterService(&service); unique_ptr<Server> server = builder.BuildAndStart(); 17 server − >Wait();

  16. RPC server implementation (starting) DirectoriesImpl service; ServerBuilder builder; builder.AddListeningPort("127.0.0.1:43534", grpc::InsecureServerCredentials()); builder.RegisterService(&service); unique_ptr<Server> server = builder.BuildAndStart(); 17 server − >Wait();

  17. RPC client implementation (method 1) unique_ptr<Channel> channel( grpc::CreateChannel("127.0.0.1:43534"), grpc::InsecureChannelCredentials())); unique_ptr<Directories::Stub> stub(Directories::NewStub(channel)); ClientContext context; MakeDirectoryArgs args; Empty empty; args.set_name("/directory/name"); 18 Status status = stub − >MakeDirectory(&context, args, &empty); if (!status.ok()) { /* handle error */ }

  18. RPC client implementation (method 1) unique_ptr<Channel> channel( grpc::CreateChannel("127.0.0.1:43534"), grpc::InsecureChannelCredentials())); unique_ptr<Directories::Stub> stub(Directories::NewStub(channel)); ClientContext context; MakeDirectoryArgs args; Empty empty; args.set_name("/directory/name"); 18 Status status = stub − >MakeDirectory(&context, args, &empty); if (!status.ok()) { /* handle error */ }

  19. RPC client implementation (method 1) unique_ptr<Channel> channel( grpc::CreateChannel("127.0.0.1:43534"), grpc::InsecureChannelCredentials())); unique_ptr<Directories::Stub> stub(Directories::NewStub(channel)); ClientContext context; MakeDirectoryArgs args; Empty empty; args.set_name("/directory/name"); 18 Status status = stub − >MakeDirectory(&context, args, &empty); if (!status.ok()) { /* handle error */ }

  20. RPC client implementation (method 1) unique_ptr<Channel> channel( grpc::CreateChannel("127.0.0.1:43534"), grpc::InsecureChannelCredentials())); unique_ptr<Directories::Stub> stub(Directories::NewStub(channel)); ClientContext context; MakeDirectoryArgs args; Empty empty; args.set_name("/directory/name"); 18 Status status = stub − >MakeDirectory(&context, args, &empty); if (!status.ok()) { /* handle error */ }

  21. RPC client implementation (method 1) unique_ptr<Channel> channel( grpc::CreateChannel("127.0.0.1:43534"), grpc::InsecureChannelCredentials())); unique_ptr<Directories::Stub> stub(Directories::NewStub(channel)); ClientContext context; MakeDirectoryArgs args; Empty empty; args.set_name("/directory/name"); 18 Status status = stub − >MakeDirectory(&context, args, &empty); if (!status.ok()) { /* handle error */ }

  22. RPC client implementation (method 2) unique_ptr<Channel> channel( grpc::CreateChannel("127.0.0.1:43534"), grpc::InsecureChannelCredentials())); unique_ptr<Directories::Stub> stub(Directories::NewStub(channel)); ClientContext context; ListDirectoryArgs args; DirectoryList list; args.set_name("/directory/name"); for ( int i = 0; i < list.entries_size(); ++i) { cout << list.entries(i).name() << endl; } 19 Status status = stub − >MakeDirectory(&context, args, &list); if (!status.ok()) { /* handle error */ }

  23. RPC client implementation (method 2) unique_ptr<Channel> channel( grpc::CreateChannel("127.0.0.1:43534"), grpc::InsecureChannelCredentials())); unique_ptr<Directories::Stub> stub(Directories::NewStub(channel)); ClientContext context; ListDirectoryArgs args; DirectoryList list; args.set_name("/directory/name"); for ( int i = 0; i < list.entries_size(); ++i) { cout << list.entries(i).name() << endl; } 19 Status status = stub − >MakeDirectory(&context, args, &list); if (!status.ok()) { /* handle error */ }

  24. RPC client implementation (method 2) unique_ptr<Channel> channel( grpc::CreateChannel("127.0.0.1:43534"), grpc::InsecureChannelCredentials())); unique_ptr<Directories::Stub> stub(Directories::NewStub(channel)); ClientContext context; ListDirectoryArgs args; DirectoryList list; args.set_name("/directory/name"); for ( int i = 0; i < list.entries_size(); ++i) { } 19 Status status = stub − >MakeDirectory(&context, args, &list); if (!status.ok()) { /* handle error */ } cout << list.entries(i).name() << endl;

  25. RPC non-transparency setup is not transparent — what server/port/etc. ideal: system just knows where to contact? errors might happen what if connection fails? server and client versions out-of-sync can’t upgrade at the same time — difgerent machines performance is very difgerent from local 20

  26. some gRPC errors method not implemented e.g. server/client versions disagree local procedure calls — linker error deadline exceeded no response from server after a while — is it just slow? connection broken due to network problem 21

  27. leaking resources? RemoteFile rfh; stub.RemoteOpen(&context, filename, &rfh); RemoteWriteRequest remote_write; remote_write.set_file(rfh); remote_write.set_data("Some text.\n"); stub.RemotePrint(&context, remote_write, ...); stub.RemoteClose(rfh); what happens if client crashes? does server still have a fjle open? related to issue of statefullness 22 ␣

  28. on versioning normal software: multiple versions of library? extra argument for function change what function does … want this for RPC, but how? 23

  29. gRPC’s versioning gRPC: messages have fjeld numbers rules allow adding new optional fjelds get message with extra fjeld — ignore it (extra fjeld includes fjeld numbers not in our source code) get message missing optional fjeld — ignore it otherwise, need to make new methods for each change …and keep the old ones working for a while 24

  30. versioned protocols ONC RPC solution: whole service has versions have implementations of multiple versions in server verison number is part of every procedures name 25

  31. RPC performance network part of remote procedure call 26 local procedure call: ∼ 1 ns system call: ∼ 100 ns (typical network) > 400 000 ns (super-fast network) 2 600 ns

  32. RPC locally not uncommon to use RPC one machine more convenient than pipes? allows shared memory implementation mmap one common fjle use mutexes+condition variables+etc. inside that memory 27

  33. network fjlesystems department machines — your fjles always there even though several machines to log into how? there’s a network fjle server fjlesystem is backed by a remote machine 28

  34. simple network fjlesystem user program kernel system calls: open("foo.txt", …) read(fd,"bar.txt",…) … login server fjle server (other machine) remote procedure calls: open("foo.txt", …) read(fd, "bar.txt", …) … 29

  35. system calls to RPC calls? just turn system calls into RPC calls? (or calls to the kernel’s internal fjleystem abstraction, e.g. Linux’s Virtual File System layer) has some problems: what state does the server need to store? what if a client machine crashes? what if the server crashes? how fast is this? 30

  36. state for server to store? open fjle descriptors? what fjle ofgset in fjle current working directory? 31 gets pretty expensive across N fjles

  37. if a client crashes? can the server delete its open fjle information yet? what if its cable is plugged back in and it works again? 32 well, it hasn’t responded in N minutes, so

  38. if the server crashes? well, fjrst we restart the server/start a new one… then, what do clients do? probably need to restart to? can we do better? 33

  39. performance usually reading/writing fjles/directories goes to local memory lots of work to have big caches, read-ahead so open/read/write/close/rename/readdir/etc. take microseconds open that fjle? yes, I have the direntry cached now they take milliseconds+ open that fjle? let’s ask the server if that’s okay can we do better? 34

  40. NFSv2 NFS (Network File System) version 2 standardized in RFC 1094 (1989) based on RPC calls 35

  41. fjle ID: opaque data (support multiple implementations) NFSv2 RPC calls (subset) example implementation: device+inode number+“generation number” “stateless protocol” — no open/close/etc. each operation stands alone 36 LOOKUP(dir fjle ID, fjlename) → fjle ID GETATTR(fjle ID) → (fjle size, owner, …) READ(fjle ID, ofgset, length) → data WRITE(fjle ID, data, ofgset) → success/failure CREATE(dir fjle ID, fjlename, metadata) → fjle ID REMOVE(dir fjle ID, fjlename) → success/failure SETATTR(fjle ID, size, owner, …) → success/failure

  42. fjle ID: opaque data (support multiple implementations) NFSv2 RPC calls (subset) example implementation: device+inode number+“generation number” “stateless protocol” — no open/close/etc. each operation stands alone 37 LOOKUP(dir fjle ID, fjlename) → fjle ID GETATTR(fjle ID) → (fjle size, owner, …) READ(fjle ID, ofgset, length) → data WRITE(fjle ID, data, ofgset) → success/failure CREATE(dir fjle ID, fjlename, metadata) → fjle ID REMOVE(dir fjle ID, fjlename) → success/failure SETATTR(fjle ID, size, owner, …) → success/failure

  43. NFSv2 client versus server client machine crashes? mapping automatically deleted “fate sharing” server: convert fjle IDs to fjles on disk typically fjnd unique number for each fjle usually by inode number server doesn’t get notifjed unless client is using the fjle 38 clients: fjle descriptor → server name, fjle ID, ofgset

  44. fjle IDs device + inode + “generation number”? generation number: incremented every time inode reused problem: client removed while client has it open later client tries to access the fjle maybe inode number is valid but for difgerent fjle inode was deallocated, then reused for new fjle Linux fjlesystems store a “generation number” in the inode basically just to help implement things like NFS 39

  45. fjle ID: opaque data (support multiple implementations) NFSv2 RPC calls (subset) example implementation: device+inode number+“generation number” “stateless protocol” — no open/close/etc. each operation stands alone 40 LOOKUP(dir fjle ID, fjlename) → fjle ID GETATTR(fjle ID) → (fjle size, owner, …) READ(fjle ID, ofgset, length) → data WRITE(fjle ID, data, ofgset) → success/failure CREATE(dir fjle ID, fjlename, metadata) → fjle ID REMOVE(dir fjle ID, fjlename) → success/failure SETATTR(fjle ID, size, owner, …) → success/failure

  46. NFSv2 RPC (more operations) (names and fjle IDs, next ofgset “cookie”) pattern: client storing opaque tokens for client: remember this, don’t worry about it tokens represent something the server can easily lookup fjle IDs: inode, etc. directory ofgset cookies: byte ofgset in directory, etc. strategy for making stateful service stateless 41 READDIR(dir fjle ID, count, optional ofgset “cookie”) →

  47. NFSv2 RPC (more operations) (names and fjle IDs, next ofgset “cookie”) pattern: client storing opaque tokens for client: remember this, don’t worry about it tokens represent something the server can easily lookup fjle IDs: inode, etc. directory ofgset cookies: byte ofgset in directory, etc. strategy for making stateful service stateless 41 READDIR(dir fjle ID, count, optional ofgset “cookie”) →

  48. things NFSv2 didn’t do well performance — each read goes to server? would like to cache things in the clients performance — each write goes to server? observation: usually only one user of fjle at a time would like to usually cache writes at clients writeback later offmine operation? would be nice to work on laptops where wifj sometimes goes out 42

  49. statefulness stateful protocol (example: FTP) previous things in connection matter e.g. logged in user e.g. current working directory e.g. where to send data connection stateless protocol (example: HTTP, NFSv2) each request stands alone servers remember nothing about clients between messages e.g. fjle IDs for each operation instead of fjle descriptor 43

  50. stateful versus stateless in client/server protocols: stateless: more work for client, less for server client needs to remember/forward any information can run multiple copies of server without syncing them can reboot server without restoring any client state stateful: more work for server, less for client client sets things at server, doesn’t change anymore hard to scale server to many clients (store info for each client rebooting server likely to break active connections 44

  51. still allows stateless server update updating cached copies? one solution: A checks on every read does B get updated version from A? how? read NOTES.txt? when does A tell server about update? write to NOTES.txt? did NOTES.txt change? how does A’s copy get updated? client A write to NOTES.txt? can A actually use its cached copy? how does A’s copy get updated? write to NOTES.txt? server client B of NOTES.txt cached copy 45

  52. still allows stateless server update updating cached copies? one solution: A checks on every read does B get updated version from A? how? read NOTES.txt? when does A tell server about update? write to NOTES.txt? did NOTES.txt change? how does A’s copy get updated? client A write to NOTES.txt? can A actually use its cached copy? how does A’s copy get updated? write to NOTES.txt? server client B of NOTES.txt cached copy 45

  53. update updating cached copies? one solution: A checks on every read does B get updated version from A? how? read NOTES.txt? when does A tell server about update? write to NOTES.txt? did NOTES.txt change? still allows stateless server how does A’s copy get updated? client A write to NOTES.txt? can A actually use its cached copy? how does A’s copy get updated? write to NOTES.txt? server client B of NOTES.txt cached copy 45

  54. still allows stateless server updating cached copies? client A does B get updated version from A? how? read NOTES.txt? when does A tell server about update? write to NOTES.txt? did NOTES.txt change? one solution: A checks on every read how does A’s copy get updated? write to NOTES.txt? can A actually use its cached copy? how does A’s copy get updated? write to NOTES.txt? server client B of NOTES.txt cached copy 45 update

  55. still allows stateless server updating cached copies? client A does B get updated version from A? how? read NOTES.txt? when does A tell server about update? write to NOTES.txt? did NOTES.txt change? one solution: A checks on every read how does A’s copy get updated? write to NOTES.txt? can A actually use its cached copy? how does A’s copy get updated? write to NOTES.txt? server client B of NOTES.txt cached copy 45 update

  56. NFSv3’s solution: allow inconsistency consistency with stateless server always check server before using cached version write through all updates to server allows server to not remember clients no extra code for server/client failures, etc. …but kinda destroys benefjt of caching many milliseconds to contact server, even if not transferring data 46

  57. NFSv3’s solution: allow inconsistency consistency with stateless server always check server before using cached version write through all updates to server allows server to not remember clients no extra code for server/client failures, etc. …but kinda destroys benefjt of caching many milliseconds to contact server, even if not transferring data 46

  58. NFSv3’s solution: allow inconsistency consistency with stateless server always check server before using cached version write through all updates to server allows server to not remember clients no extra code for server/client failures, etc. …but kinda destroys benefjt of caching many milliseconds to contact server, even if not transferring data 46

  59. consistency with stateless server always check server before using cached version write through all updates to server allows server to not remember clients no extra code for server/client failures, etc. …but kinda destroys benefjt of caching many milliseconds to contact server, even if not transferring data 46 NFSv3’s solution: allow inconsistency

  60. typical text editor/word processor typical word processor: opening a fjle: open fjle, read it, load into memory, close it saving a fjle: open fjle, write it from memory, close it 47

  61. two people saving a fjle? have a word processor document on shared fjlesystem Q: if you open the fjle while someone else is saving, what do you expect? Q: if you save the fjle while someone else is saving, what do you expect? observation: not things we really expect to work anyways most applications don’t care about accessing fjle while someone has it open 48

  62. two people saving a fjle? have a word processor document on shared fjlesystem Q: if you open the fjle while someone else is saving, what do you expect? Q: if you save the fjle while someone else is saving, what do you expect? observation: not things we really expect to work anyways most applications don’t care about accessing fjle while someone has it open 48

  63. open to close consistency a compromise: opening a fjle checks for updated version otherwise, use latest cache version closing a fjle writes updates from the cache otherwise, may not be immediately written idea: as long as one user loads/saves fjle at a time, great! 49

  64. open to close consistency a compromise: opening a fjle checks for updated version otherwise, use latest cache version closing a fjle writes updates from the cache otherwise, may not be immediately written idea: as long as one user loads/saves fjle at a time, great! 49

  65. an alternate compromise application opens a fjle, read it a day later, result? day-old version of fjle modifjcation 1: check server/write to server after an amount of time doesn’t need to be much time to be useful 50 word processor: typically load/save fjle in < second

  66. AFSv2 Andrew File System version 2 also works fjle at a time — not parts of fjle i.e. read/write entire fjles but still chooses consistency compromise still won’t support simulatenous read+write from difg. machines well stateful: avoids repeated ‘is my fjle okay?’ queries 51 uses a stateful server

  67. NFS versus AFS reading/writing NFS reading: read/write block at a time AFS reading: always read/write entire fjle exercise: pros/cons? effjcient use of network? what kinds of inconsistency happen? does it depend on workload? 52

  68. AFS: last writer wins on client A on client B open NOTES.txt open NOTES.txt write to cached NOTES.txt write to cached NOTES.txt close NOTES.txt AFS: write whole fjle close NOTES.txt AFS: write whole fjle last writer wins 53

  69. NFS: last writer wins per block close NOTES.txt NOTES.txt: 0 from B, 1 from A, 2 from B NFS: write NOTES.txt block 2 NFS: write NOTES.txt block 2 NFS: write NOTES.txt block 1 NFS: write NOTES.txt block 1 NFS: write NOTES.txt block 0 NFS: write NOTES.txt block 0 on client A close NOTES.txt write to cached NOTES.txt write to cached NOTES.txt open NOTES.txt open NOTES.txt on client B 54

  70. AFS caching (A, NOTES.txt) NOTES.txt updated write NOTES.txt register callback fetch NOTES.txt + register callback fetch NOTES.txt + callbacks: client A of NOTES.txt cached copy of NOTES.txt cached copy server client B 55

  71. AFS caching (A, NOTES.txt) NOTES.txt updated write NOTES.txt register callback fetch NOTES.txt + register callback fetch NOTES.txt + callbacks: client A of NOTES.txt cached copy of NOTES.txt cached copy server client B 55

  72. AFS caching (B, NOTES.txt) NOTES.txt updated write NOTES.txt register callback fetch NOTES.txt + register callback fetch NOTES.txt + (A, NOTES.txt) client A callbacks: of NOTES.txt cached copy of NOTES.txt cached copy server client B 55

  73. AFS caching (B, NOTES.txt) NOTES.txt updated write NOTES.txt register callback fetch NOTES.txt + register callback fetch NOTES.txt + (A, NOTES.txt) client A callbacks: of NOTES.txt cached copy of NOTES.txt cached copy server client B 55

  74. callback inconsistency (1) close NOTES.txt are not accessing fjle from two places at once close-to-open consistency assumption: (could fjx by notifying server earlier) because server doesn’t same issue w/NFS: B can’t know about write problem with close-to-open consistency (AFS: callback: NOTES.txt changed) (write to server) write to cached NOTES.txt on client A read from NOTES.txt write to cached NOTES.txt read from NOTES.txt (NOTES.txt fetched) open NOTES.txt read from cached NOTES.txt (AFS: NOTES.txt fetched) open NOTES.txt on client B 56

  75. callback inconsistency (1) close NOTES.txt are not accessing fjle from two places at once close-to-open consistency assumption: (could fjx by notifying server earlier) because server doesn’t same issue w/NFS: B can’t know about write problem with close-to-open consistency (AFS: callback: NOTES.txt changed) (write to server) write to cached NOTES.txt on client A read from NOTES.txt write to cached NOTES.txt read from NOTES.txt (NOTES.txt fetched) open NOTES.txt read from cached NOTES.txt (AFS: NOTES.txt fetched) open NOTES.txt on client B 56

  76. callback inconsistency (1) close NOTES.txt are not accessing fjle from two places at once close-to-open consistency assumption: (could fjx by notifying server earlier) because server doesn’t same issue w/NFS: B can’t know about write problem with close-to-open consistency (AFS: callback: NOTES.txt changed) (write to server) write to cached NOTES.txt on client A read from NOTES.txt write to cached NOTES.txt read from NOTES.txt (NOTES.txt fetched) open NOTES.txt read from cached NOTES.txt (AFS: NOTES.txt fetched) open NOTES.txt on client B 56

  77. 57

  78. HTTP protocol (simplifjed) <CR><LF> no association with previous message send new message end indicated by supplied length (in this case) response always includes status code solution: two CRLF (C: "\r\n" ) need some way to fjnd end-of-message sent over TCP — stream of arbitrarily many bytes hostname in message — only IP address available otherwise request has path + key-value pairs… or sending fjle/form HTTP: send message requesting fjle … Accept: text/html, *;q=0.9 <CR><LF> client Host: www.cs.virginia.edu <CR><LF> GET / cr4bd/4414/F2018/assignemnts.html HTTP/1.1 <CR><LF> (contents of fjle schedule.html) <CR><LF> Content-Length: 38329 <CR><LF> Content-Type: text/html <CR><LF> HTTP/1.1 200 OK <CR><LF> <CR><LF> Accept: text/html, *;q=0.9 <CR><LF> Host: www.cs.virginia.edu <CR><LF> GET / cr4bd/4414/F2018/schedule.html HTTP/1.1 <CR><LF> server 58

  79. HTTP protocol (simplifjed) <CR><LF> no association with previous message send new message end indicated by supplied length (in this case) response always includes status code solution: two CRLF (C: "\r\n" ) need some way to fjnd end-of-message sent over TCP — stream of arbitrarily many bytes hostname in message — only IP address available otherwise request has path + key-value pairs… or sending fjle/form HTTP: send message requesting fjle … Accept: text/html, *;q=0.9 <CR><LF> client Host: www.cs.virginia.edu <CR><LF> GET / cr4bd/4414/F2018/assignemnts.html HTTP/1.1 <CR><LF> (contents of fjle schedule.html) <CR><LF> Content-Length: 38329 <CR><LF> Content-Type: text/html <CR><LF> HTTP/1.1 200 OK <CR><LF> <CR><LF> Accept: text/html, *;q=0.9 <CR><LF> Host: www.cs.virginia.edu <CR><LF> GET / cr4bd/4414/F2018/schedule.html HTTP/1.1 <CR><LF> server 58

Recommend


More recommend