Sock-06.チャットっぽいなにかを作って流れを確認2
今回のお題
フローチャートを確認しつつ簡易的なチャットっぽいなにかを作ってみよう
今回のプログラムは
コンソールアプリケーション ※DxLibは使わない!
TCP
交互に文字列を送受信
サーバ
1. ヘッダ・ライブラリ
必要なヘッダインクルードしたり、ライブラリを追加したりする
code:Server03.cpp
2. WinSockの初期化と終了処理
初期化はしたけど、終了処理は忘れた!…ってならないように、初期化と終了まとめて書いておこう
code:Server03.cpp
int main()
{
// WinSockの初期化処理 WinSock2.2
// WinSockの終了処理
}
3. TCPソケットの作成とソケットの破棄
アドレスファミリ:AF_INET
ソケットタイプ:SOCK_STREAM
プロトコル:IPPROTO_TCP
0でもok
エラーが出たら、エラーコードを出力しつつ終了させてしまおう
エラーコード:WSAGetLastError()で直近のエラーコードが取得可能
code:Server03.cpp
int main()
{
// WinSockの初期化処理 WinSock2.2
// TCPリスンソケットの作成
// TCPリスンソケットの破棄
// WinSockの終了処理
}
4. 3で作ったソケットに固定ポート番号を割り当てる
SOCKADDR_IN構造体の変数を用意
メンバ変数に必要な値をセット
bindで固定のポート番号を割り当てる
code:Server03.cpp
int main()
{
// WinSockの初期化処理 WinSock2.2
// TCPリスンソケットの作成
// ポート番号割り当て
// TCPリスンソケットの破棄
// WinSockの終了処理
}
通信する2つのプログラムでどちらも固定のポート番号割り当てても別にだめじゃない
C/S型だとサーバは固定、クライアントはエフェメラルポートってイメージだけど、どっちも固定にすればP2Pちっくになる
5. リスンソケットをリスン状態にする
ソケットを作成しただけではコネクションは確立できない
リスン状態( 外部からのコネクション確立要求を受け付け可能な状態 )にする必要がある
code:Server03.cpp
int main()
{
// WinSockの初期化処理 WinSock2.2
// TCPリスンソケットの作成
// ポート番号割り当て
// TCPリスンソケットをリスン状態にする
// TCPリスンソケットの破棄
// WinSockの終了処理
}
listen()の第2引数は、接続要求待ち行列の最大長
SOMAXCONN にすると妥当な数が割り当てられるらしい
6. クライアントからの接続要求待ち( コネクション確立要求待ち )
サーバはクライアントが「コネクション確立したい!」って言ってくるのを待つ
→新たなソケットが生み出され、そのソケットとクライアントのソケットとの間にコネクションが確立される
あらたに生み出されたソケットにはbindは不要。OS自動割り当てのポート番号を使う
code:Server03.cpp
int main()
{
// WinSockの初期化処理 WinSock2.2
// TCPリスンソケットの作成
// ポート番号割り当て
// TCPリスンソケットをリスン状態にする
// 接続要求待ち ※ブロッキング発生:接続要求受付→コネクション確立でブロッキング解除
// 送受信切断
// コネクション確立したソケットの破棄
// TCPリスンソケットの破棄
// WinSockの終了処理
}
こそっと破棄も追記
7. クライアントからの受信…以下略
受信→出力→文字列入力→送信
code:Server03.cpp
int main()
{
// WinSockの初期化処理 WinSock2.2
// TCPリスンソケットの作成
// ポート番号割り当て
// TCPリスンソケットをリスン状態にする
// 接続要求待ち ※ブロッキング発生:接続要求受付→コネクション確立でブロッキング解除
// 受信
// 出力
// 文字列入力
// 送信
// コネクション確立したソケットの破棄
// 送受信切断
// TCPリスンソケットの破棄
// WinSockの終了処理
}
クライアント
1. ヘッダ・ライブラリ~ 2. 宛先( サーバ )のアドレスをセット!
UDPのクライアントと基本は一緒
ソケット作るときにTCPにするだけ
code:Cliemt03.cpp
int main()
{
// WinSockの初期化処理 WinSock2.2
// TCPソケットの作成
// 宛先のアドレス情報セット
// TCPソケットの破棄
// WinSockの終了処理
}
2. 接続要求
1で作成したソケットとサーバとの間にコネクション確立したいよー
code:Client03.cpp
int main()
{
// WinSockの初期化処理 WinSock2.2
// TCPソケットの作成
// 宛先のアドレス情報セット
// 接続要求 ブロッキング発生:接続要求受付→コネクション確立でブロッキング解除
// 送受信切断
// TCPソケットの破棄
// WinSockの終了処理
}
3. サーバに送信…以下略!
文字列入力→送信→受信→出力
code:Client02.cpp
int main()
{
// WinSockの初期化処理 WinSock2.2
// TCPソケットの作成
// 宛先のアドレス情報セット
// 接続要求 ブロッキング発生:接続要求受付→コネクション確立でブロッキング解除
// 文字列入力
// 送信
// 受信
// 出力
// 送受信切断
// TCPソケットの破棄
// WinSockの終了処理
}