質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

TCP

TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

Q&A

解決済

1回答

929閲覧

Rubyでのソケット通信で接続を解除できなくなった

退会済みユーザー

退会済みユーザー

総合スコア0

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

TCP

TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

0グッド

0クリップ

投稿2021/11/28 02:36

編集2021/11/30 06:56
コード ```### 前提・実現したいこと ここに質問の内容を詳しく書いてください。 Ruby初心者です。学校の授業で習い、課題のために以下のプログラムを作成しました。 ```Ruby require "socket" require 'date' require 'time' server = TCPServer.new(20000) loop do Thread.start(server.accept) do |client| # 初回クライアントに伝えるメッセージ client.puts "サーバーに接続されました。" loop do line = client.gets # p line break if line == nil # 送られてきたメッセージがnilだったらループ終わり # 改行を取り除くのと、文字コードをUTF8に強制変更 line = line.chomp.force_encoding("utf-8") # サーバー側に出力 puts "受信: #{line}" # 受信したメッセージに対する何らかの処理を実装する # サンプルで、受け取ったメッセージをそのまま出力 # ret = line # client.puts "サーバーからの応答: #{ret}" if(line == 'date') client.puts Date.today elsif(line == 'time') client.puts Time.now end end end end

その後ターミナルから「nc localhost 20000」で実行したのですが、「Control+C」を試しても何も起こらず、ターミナルにdateを入力すると日付が返ってきてしまう状態です。

発生している問題・エラーメッセージ

接続がずっとつながったままで、プログラムを更新しても反映することが出来ません。
他のポート番号にもつながらないです。

該当のソースコード

Ruby

1require "socket" 2require 'date' 3require 'time' 4 5server = TCPServer.new(20000) 6loop do 7 Thread.start(server.accept) do |client| 8 9 # 初回クライアントに伝えるメッセージ 10 client.puts "サーバーに接続されました。" 11 12 loop do 13 14 line = client.gets 15 # p line 16 break if line == nil # 送られてきたメッセージがnilだったらループ終わり 17 18 # 改行を取り除くのと、文字コードをUTF8に強制変更 19 line = line.chomp.force_encoding("utf-8") 20 21 # サーバー側に出力 22 puts "受信: #{line}" 23 # 受信したメッセージに対する何らかの処理を実装する 24 25 # サンプルで、受け取ったメッセージをそのまま出力 26 # ret = line 27 # client.puts "サーバーからの応答: #{ret}" 28 29 if(line == 'date') 30 client.puts Date.today 31 elsif(line == 'time') 32 client.puts Time.now 33 34 end 35 end 36end 37end

試したこと

netstat -atn|grep LISTENをターミナルに入力してみましたが、localhostで出てきたのはこの二つだけでした。
tcp4 0 0 localhost.49182 localhost.55205 ESTABLISHED
tcp4 0 0 localhost.55205 localhost.49182 ESTABLISHED
想定していないポート番号で接続されているのかもしれませんが、解決法がわかりません。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2021/11/28 02:38

このままではコードが読みづらいので、質問を編集し、<code>ボタンを押し、出てくる’’’の枠の中にコードを貼り付けてください
退会済みユーザー

退会済みユーザー

2021/11/29 01:10

ご指摘ありがとうございます。 teratailで質問を投稿するのも初めてだったので、全然理解していませんでした。すみません。
melian

2021/11/29 01:14

netstat -atn|grep LISTEN ではなく、 netstat -tln とすれば LISTEN 状態にある TCP ポートのみを表示してくれます(grepでフィルタリングする必要はありません)。
maisumakun

2021/11/29 01:17

そもそも、元のコードでendの数が合わないようですが、それは間違いないですか?
退会済みユーザー

退会済みユーザー

2021/11/29 02:00 編集

endの数が合わないのは間違い無いですが、初めに実行した際のコードはこれだったと思います。
melian

2021/11/29 01:45

if(line == date) となっていますが、これは if(line == 'date') ではないでしょうか?(elsif(line == time) も同様)
退会済みユーザー

退会済みユーザー

2021/11/29 02:06

netstat -tin を入力したら Name Mtu Network Address Ipkts Ierrs Opkts Oerrs Coll Time lo0 16384 <Link#1> 16003 0 16003 0 0 0 lo0 16384 127 127.0.0.1 16003 - 16003 - - - lo0 16384 ::1/128 ::1 16003 - 16003 - - - lo0 16384 fe80::1%lo0 fe80:1::1 16003 - 16003 - - - gif0* 1280 <Link#2> 0 0 0 0 0 0 stf0* 1280 <Link#3> 0 0 0 0 0 0 en0 1500 <Link#4> 94:f6:d6:1b:e4:c0 923532 0 568651 0 0 0 en0 1500 fe80::c61:d fe80:4::c61:db9b: 923532 - 568651 - - - en0 1500 192.168.68 192.168.68.105 923532 - 568651 - - - en1 1500 <Link#5> 82:18:60:eb:af:40 0 0 0 0 0 0 bridge0 1500 <Link#6> 82:18:60:eb:af:40 0 0 0 0 0 0 p2p0 2304 <Link#7> 06:f6:d6:1b:e4:c0 0 0 0 0 0 0 awdl0 1484 <Link#8> c2:f6:84:85:b6:1d 1450 0 455 0 0 0 awdl0 1484 fe80::c0f6: fe80:8::c0f6:84ff 1450 - 455 - - - llw0 1500 <Link#9> c2:f6:84:85:b6:1d 0 0 0 0 0 0 llw0 1500 fe80::c0f6: fe80:9::c0f6:84ff 0 - 0 - - - utun0 1380 <Link#10> 0 0 2 0 0 0 utun0 1380 fe80::813a: fe80:a::813a:e2a9 0 - 2 - - - utun1 2000 <Link#11> 0 0 2 0 0 0 utun1 2000 fe80::dcd3: fe80:b::dcd3:ffd1 0 - 2 - - - utun2 1000 <Link#12> 0 0 2 0 0 0 utun2 1000 fe80::ce81: fe80:c::ce81:b1c: 0 - 2 - - - utun3 1380 <Link#13> 216 0 219 0 0 0 utun3 1380 fe80::bb4e: fe80:d::bb4e:c8be 216 - 219 - - - utun4 1380 <Link#14> 0 0 2 0 0 0 utun4 1380 fe80::f9e4: fe80:e::f9e4:c846 0 - 2 - - - が出力されました。
melian

2021/11/29 02:12

i ではなく l です。 netstat -tlp
退会済みユーザー

退会済みユーザー

2021/11/29 02:20

if(line == date)の間違いに気がつきませんでした。if(line == 'date')が正しいと思います。 しかし、今の状態だとコードを更新して保存しても反映されないので、例えばif文のところをまるごと消してもdateと入力すれば日付が返ってきてしまいます。 実行した時点でのコードではif(line == date)にしていたと思うのですが、一番最初の実行自体はできているのでif(line == 'date')となっていたのをどこかで変えてしまったのかもしれません。曖昧な返信しかできなくてすみません。
退会済みユーザー

退会済みユーザー

2021/11/29 02:22

自分でも何も理解できていないまま、ネットの情報で色々試してしまったので、どうしようもできない状態になっているのかもしれません。すみません。
otn

2021/11/29 13:13

他の方がコメントされているように、質問文に掲載しているコードは、今あなたが実際に実行して困っているコードではありません。間違ったコードを元に考えるのは無意味なので、今あなたが実行しているコードに差し替えましょう。
otn

2021/11/30 07:31

問題点としては、クライアントから切断する手段が無いと言うことだけでしょうか? それ以外に何か問題点はありますか?
退会済みユーザー

退会済みユーザー

2021/11/30 09:35

切断する手段が無いことだけです。
guest

回答1

0

ベストアンサー

クライアント主導で操作する場合に、ソケットを切断するには、
・クライアントでソケットをクローズする
・クライアントからサーバーに終了を伝えてサーバー側でソケットをクローズする(sshでログアウトするようなケース)
のどちらかです。

クライアントとしてnetcatのような汎用ツールを使って、それがCtrl-C等を受け付けないとすると、netcatプロセスをkillコマンドで終了させるくらいでしょうか。

あるいは、サーバー側に「クライアントから"quit"が入力されたらソケットをクローズする」という機能を追加するとか。

手元のncコマンドだとCtrl-Cが効きます。

投稿2021/11/30 10:16

otn

総合スコア85901

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/12/01 03:23

killしたいもののポート番号、PIDを知るにはどうしたらいいですか?
otn

2021/12/01 04:01

killはプロセスに対して行うので、ポート番号は関係ないです。 別の端末で、psコマンドを実行すればわかります。 あるいは、Unix/Linuxなら、Ctrl-Z で中断できるので、そこで kill %nc とか。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問