TCP/IPスロットによるサーバ実装
10638 ワード
緒論
学習目標📖
本題
学習のきっかけ
TCP/IPソケットでネットワーク通信実施コースに参加した.
勉強しておく
サーバを実装する前に、理解すべき概念を把握し、段階的に実装します.
インターネットとインターネットの違い
二人は同じじゃないですか.
ネットとネットは同じだと思っている人もいるが、両者はまったく違う.
もしもし、ネットはだめですか.
もしもし、サイトはだめですか?
上の文を聞いたら何の答えがありますか.
A:「もしもし、インターネットができませんよ.
B:「ワイヤレスネットワークが接続されていますか.切れたのではないでしょうか.」
上記の文章から、インターネットはネットワークを意味することがわかります.
A:「へえ、サイトはダメなの?」
B:「ええ、さっきは、サーバーが壊れたみたいです」
上記の文章から、ウェブサイトはネットワーク内のサービスを意味していることがわかります.
すなわち、インターネットは相互に接続されたネットワークを意味し、Webはその接続されたネットワーク上で提供されるサービスである.
サイトには様々なサイトが存在し、サイトは複数のページから構成されています.
そしてそのページを見るために、私たちはウェブブラウザを使っています.
誰もがWebブラウザ、サイト、ページの名前を持っている理由がわかります.
サーバとは
これはアルバイトで使う単語ではありませんか.
そうだ.
アルバイト用の言葉.
Server = Serve + er
サービス:提供する
≪サーバー|Server|ldap≫:≪プロバイダ|Provider|ldap≫
レストランでお客さんが「おい!とんかつラーメンをください!そう言えば、「はい、わかりました.ドンゴズです」とサーバーです.
ネット上でもそうです.
プログラムまたはハードウェアの一部として他のデバイスに機能を提供する...
これらはいらないと大雑把に考え、お願いさえあれば答えられる.
Web上では、クライアントとサーバがファイルを要求して応答します.
スロットとは?
コンセントはコンセントですか?
TCP/IPスロットを使用してサーバを実装するとおっしゃいましたが、スロットが何なのかを調べてみましょう.
コンセントを検索するときに表示される画像はコンセントです.
まず過去はどのように通信していたのでしょうか.
簡単に言えば、2台のコンピュータがあれば、通信のために銅線しか必要ありません.
銅線で私のパソコンに1本差し込み、相手のパソコンに1本差し込み、電気信号交換を行います.これが通信です.
このように、電気信号を出すとき、出入りする場所がコンセントです.
では正義に戻ります.
「ネットワークソケットは、ネットワークからデータを送信および受信するエンドポイントであり、ソフトウェア構造を使用してネットワークノードを...」
いったいどうしてこんなことになったの?もちろん分からない.
さすがに壮大さはいらないこれらは出入り口と考えればいいだけ
コンセントを差し込んで電子製品を使用するように、コンセントという接点、出入り口を作成し、データを交換します.
それでも理解できないなら、楽天ワールドを考えてみましょう.
彗星特急に乗って入場し、アトラクションで反対側に行くのを待っていますか?
私たちは流量で、アトラクションで移動したのは流れで、入場と出たのはそれぞれコンセントです.
URLはどのように組織されていますか?
[プロトコル]:/{[アイデンティティ]:[パスワード]@}[サーバアドレス]{:ポート番号}[リソースパス]{?クエリー}{#ハッシュ}
ソケットを用いてWeb通信を行う方法を知る前に,URLがどのように構成されているかを知る必要がある.
URL:統合リソースの場所の略を以下に示します.
[プロトコル]:/{[アイデンティティ]:[パスワード]@}[サーバアドレス]{:ポート番号}[リソースパス]{?クエリー}{#ハッシュ}
[]は必須ですが、{}は省略できます.
ポート番号などの場合、デフォルトのポート番号でない場合は、デフォルトのポート番号は次のように指定する必要があります.
http : 80
https : 443
ftp : 21
ssh/sftp : 22
telent : 23
つうしんげんり
基本的な用語や概念を学んでいる以上、通信の原理を理解してみましょう.
データ通信を無条件に行うには、任意のプログラムにソケットが必要です.
入り口があってこそ流量があるのではないでしょうか.
では、このソケットはどのように生成されるのでしょうか.TCP/IP接続でソケットが生成されます.
このソケットでデータを交換すると、データはバッファオブジェクトにストリームされます.
生成されたソケット上でWebを介してデータを交換する際に用いられるプロトコルがHTTPである.
ここで重要なのは,データ通信を行うのに無条件にWebを使用するわけではないことである.
銅線で2台のパソコンを接続し、交換すれば、ネットを使わなくても通信できるのではないでしょうか.
HTTPは、インターネット上でWebサービスを利用する際に使用されるプロトコルです.
もしあなたが実施しているチャットプログラムにWebブラウザがなければ、プログラム間でデータを交換するだけですか?
HTTPプロトコルは使用できません.
上図はTCP/IP層図であり、以下の層により上層を用いると理解される.
図にはないが、HTTPプロトコルが最上位層、すなわちTCP/IPベースのプロトコルにあることがわかる.
サーバ実装
Request Message
いよいよサーバ実装段階です.
リアルタイムストリームのように、パケット転送が信頼性よりも優先される場合、基本的にはTCPによってソケットが作成され、通信される.const net = require('net');
const server = net.createServer(socket=>{
socket.on("data",buffer=>{
console.log(buffer.toString());
})
});
server.listen(4000);
NodeJSを実行してブラウザを開き、127.0.0.1:4000と入力します.
上の図は、ブラウザがサーバに送信するrequestメッセージを示しています.
最初の行
GET/HTTP/1.1
隔写に分けて、意味は以下の通りです.
HTTP Method, Resource Location, HTTP Version
GETメソッドリクエスト、リソースロケーションルート、HTTPバージョン1.1.
2行目~最後の行
Host: 127.0.0.1:4000
KeyとValueで構成されているこの部分はRequest Headerと呼ばれています
Request Headerには複数の項目が含まれていますが、HTTPリストによると、Host部分が必要です.
私はパソコンでサーバーを実行しているので、IPアドレス127.0.0.1とポート番号4000を確認することができます.
Response Message
サーバはリクエストを受信し、対応する応答を与える必要があります.
では、私たちはどんなメッセージを送るべきですか?
確認のために、「naver.com」に接続し、リクエストメッセージを送信したときに、NAVERが応答メッセージをどのように送信したかを確認します.const net = require('net');
const socket = net.createConnection(80,"naver.com",()=>{
socket.write(`
GET / HTTP/1.1
Host: naver.com
`);
socket.on("data",buffer=>{
console.log(buffer.toString());
});
})
最初の行とRequestの必須タイトルHostだけを置いてテストしましょう
NodeJSを実行すると、次のメッセージが表示されます.
応答メッセージを説明します.
最初の行
HTTP/1.1 302 Moved Temporarily
HTTP Version, Status Code, Status Message
HTTP 1.1バージョン、302コードを使用して、一時的に移動する情報.
Status Codeはサーバ上で要求に適合する応答コードを表し,各応答コードの意味は以下の通りである.
2 xx:正常処理
3 xx:リソースが他のアドレスに移動しました
4 xx:リソースが存在しないか、処理できない
5 xx:Webサーバ内部でエラー
2行目~7行目
KeyとValueで構成されており、この部分は応答ヘッダです.
レスポンスヘッダでは、コンテンツタイプとコンテンツ長が必要です.
9行目~最後の行
htmlタグが表示されます.これはサーバが送信した内容です.
Server
応答メッセージが確認された以上、最初のタスクをアップグレードし、naverのように応答するサーバを作成しましょう.const net = require('net');
const fs = require('fs');
const server = net.createServer(socket=>{
socket.on("data",buffer=>{
const requestMessage = buffer.toString();
const [first] = requestMessage.split('\r\n');
let [method, resource, version] = first.split(' ');
if(resource[resource.length - 1] === "/"){
resource += "index.html";
}
if(fs.existsSync("./source"+resource)){
const content = fs.readFileSync("./source"+resource);
socket.write(Buffer.from("HTTP/1.1 200 OK\r\n"));
socket.write(Buffer.from("Content-Type: text/html\r\n"));
socket.write(Buffer.from(`Content-Length: ${content.length}\r\n`));
socket.write(Buffer.from("\r\n"));
socket.write(content);
socket.write(Buffer.from("\r\n"));
return;
}
const content = `<!doctype html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body>
<h1>NOT FOUND</h1></body></html>`;
socket.write(Buffer.from("HTTP/1.1 404 Not Found\r\n"));
socket.write(Buffer.from("Content-Type: text/html\r\n"));
socket.write(Buffer.from(`Content-Length: ${content.length}\r\n`));
socket.write(Buffer.from("\r\n"));
socket.write(content);
socket.write(Buffer.from("\r\n"));
})
});
server.listen(4000);
脚本は以下の通り.
const net = require('net');
const server = net.createServer(socket=>{
socket.on("data",buffer=>{
console.log(buffer.toString());
})
});
server.listen(4000);
const net = require('net');
const socket = net.createConnection(80,"naver.com",()=>{
socket.write(`
GET / HTTP/1.1
Host: naver.com
`);
socket.on("data",buffer=>{
console.log(buffer.toString());
});
})
const net = require('net');
const fs = require('fs');
const server = net.createServer(socket=>{
socket.on("data",buffer=>{
const requestMessage = buffer.toString();
const [first] = requestMessage.split('\r\n');
let [method, resource, version] = first.split(' ');
if(resource[resource.length - 1] === "/"){
resource += "index.html";
}
if(fs.existsSync("./source"+resource)){
const content = fs.readFileSync("./source"+resource);
socket.write(Buffer.from("HTTP/1.1 200 OK\r\n"));
socket.write(Buffer.from("Content-Type: text/html\r\n"));
socket.write(Buffer.from(`Content-Length: ${content.length}\r\n`));
socket.write(Buffer.from("\r\n"));
socket.write(content);
socket.write(Buffer.from("\r\n"));
return;
}
const content = `<!doctype html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body>
<h1>NOT FOUND</h1></body></html>`;
socket.write(Buffer.from("HTTP/1.1 404 Not Found\r\n"));
socket.write(Buffer.from("Content-Type: text/html\r\n"));
socket.write(Buffer.from(`Content-Length: ${content.length}\r\n`));
socket.write(Buffer.from("\r\n"));
socket.write(content);
socket.write(Buffer.from("\r\n"));
})
});
server.listen(4000);
例は基本的にGET要求を前提として実装されるが、GET、POST、PUT、DELETEに従ってブランチ処理も必要であり、多くのHeaderを操作することができる.
n/a.結論
上記の例では、ExpressやSpringBootなどのフレームワークが内部でどのように動作しているかを説明します.
簡単なappですget(), app.post()を使用すると、内部は要求メッセージを解釈し、対応する応答メッセージ送信を生成する.
時間やレベルならexpress sourceを開いて説明するのも役立ちますので参考にしてみましょう
Reference
この問題について(TCP/IPスロットによるサーバ実装), 我々は、より多くの情報をここで見つけました
https://velog.io/@jewoo/TCPIP-소켓으로-서버-구현하기
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
Reference
この問題について(TCP/IPスロットによるサーバ実装), 我々は、より多くの情報をここで見つけました https://velog.io/@jewoo/TCPIP-소켓으로-서버-구현하기テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol