Java Network Programming_Server socket
(コースの概要)
Sockets for Server
Sockets for Server
サーバとは
お客様の対話対象.クライアントがsocketを生成するには、接続するインターネット上のホストが必要です.
->サーバ
Java Socketクラスはサーバを作成できないため、Server Socketクラスを使用します。
オブジェクトのライフサイクル
1.ServerSocket()ジェネレータを使用して、特定のポートに対してServerSocketオブジェクトを作成します。
2.サーバソケットオブジェクトのaccept()メソッドを呼び出してクライアントの接続要求を待つ
accept()メソッドは、クライアントがサーバに接続しようとするまでブロックされます。
クライアントが要求を発行すると、Socketオブジェクトが返されます。
3.クライアントと通信するために、SocketオブジェクトのgetInputStream()とgetOutputStream()を使用してIOストリームオブジェクトを生成します。
4.接続が完了する前に、クライアントとサーバはアプリケーションプロトコルに従って対話する。
インタラクションは通常Threadとして処理される。
5.サーバー、クライアント、または両方の接続を閉じる
6.Step 2に戻り、次の接続要求を待つ
public Socket accept() throws IOException
クライアント接続要求を受け入れる方法
クライアントの接続要求がブロックされるまで.
クライアントが接続要求を発行すると、Socketオブジェクトが返されます.
<コメント>
ServerSocketからの例外はサーバーをシャットダウンする必要がありますが、Socketの例外はアクティブなSocketをシャットダウンするだけです.
socketオブジェクトのclose()メソッド
ローカルホストとリモートホストの接続が切断されます.
サービスが終了したら、Socketオブジェクトを閉じる必要があります.(通常はfinally構文で接続を終了します.)
例)DayTime Server
import java.net.*;
import java.io.*;
import java.util.Date;
public class DaytimeServer {
public final static int PORT = 13;
public static void main(String[] args) {
try (ServerSocket server = new ServerSocket(PORT)) {
while (true) {
try (Socket connection = server.accept()) {
Writer out = new OutputStreamWriter(connection.getOutputStream());
Date now = new Date();
out.write(now.toString() +"\r\n");
out.flush();
connection.close();
} catch (IOException ex) {}
}
} catch (IOException ex) {
System.err.println(ex);
}
}
}
例2)友人サーバとクライアント
サーバコード:
import java.io.*;
import java.net.*;
public class FriendServer {
public static void main(String[] args) {
Socket socket = null;
InputStreamReader isr = null;
OutputStreamWriter osw = null;
StringBuilder message = null;
try (ServerSocket serverSocket = new ServerSocket(7009);) {
System.out.println("-- 서버가 접속을 기다린다 -- ");
socket = serverSocket.accept();
System.out.println("-- 클라이언트와 접속 성공 -- ");
// Message from Client to Server
isr = new InputStreamReader(
socket.getInputStream(), "MS949");
message = new StringBuilder();
for (int c = isr.read(); c != -1; c = isr.read()) {
message.append((char) c);
}
socket.shutdownInput();
System.out.println("클라이언트 친구로부터 받은 메세지 : " + message);
// Message from Server to Client
osw = new OutputStreamWriter(
socket.getOutputStream() );
osw.write("나 9시에 갈 예정이야" + "\r\n");
System.out.println("클라이언트 친구에게 메시지를 보내다");
osw.flush();
socket.shutdownOutput();
osw.close();
isr.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
クライアントコード:
import java.io.*;
import java.net.*;
public class FriendClient {
public static void main(String[] args) {
InputStreamReader isr = null;
OutputStreamWriter osw = null;
StringBuilder reply = null;
try (Socket socket = new Socket("localhost", 7009)) {
socket.setSoTimeout(2000);
// Message from Client to Server
osw = new OutputStreamWriter(
socket.getOutputStream() );
osw.write("내일 학교에 몇 시에 올래" + "\r\n");
System.out.println("서버 친구에게 메시지를 보내다");
osw.flush();
socket.shutdownOutput();
// Message from Server to Client
isr = new InputStreamReader(
socket.getInputStream(), "MS949");
reply = new StringBuilder();
for (int c = isr.read(); c != -1; c = isr.read()) {
reply.append((char) c);
}
System.out.println("서버 친구로부터 받은 메세지 : " + reply);
osw.close();
isr.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
サーバを開き、クライアントから問い合わせます.明日何時に学校に来ますか.
サーバが回答します.9時に行くつもりです.
Multithreaded Server
サーバは1つのリクエストのみを処理できません.
import java.net.*;
import java.io.*;
import java.util.Date;
public class MultithreadedDaytimeServer {
public final static int PORT = 13;
public static void main(String[] args) {
try (ServerSocket server = new ServerSocket(PORT)) {
while (true) {
try {
Socket connection = server.accept();
Thread task = new DaytimeThread(connection);
task.start();
} catch (IOException ex) {}
}
} catch (IOException ex) {
System.err.println("Couldn't start server");
}
}
private static class DaytimeThread extends Thread {
private Socket connection;
DaytimeThread(Socket connection) {
this.connection = connection;
}
public void run() {
try {
Writer out = new OutputStreamWriter(connection.getOutputStream());
Date now = new Date();
out.write(now.toString() +"\r\n");
out.flush();
} catch (IOException ex) {
System.err.println(ex);
} finally {
try {
connection.close();
} catch (IOException e) {
// ignore;
}
}
}
}
}
socket値を返します。
#+Threadpoolを使用したサーバimport java.io.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.*;
public class PooledDaytimeServer {
public final static int PORT = 13;
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(50);
try (ServerSocket server = new ServerSocket(PORT)) {
while (true) {
try {
Socket connection = server.accept();
Callable<Void> task = new DaytimeTask(connection);
pool.submit(task);
} catch (IOException ex) {}
}
} catch (IOException ex) {
System.err.println("Couldn't start server");
}
}
private static class DaytimeTask implements Callable<Void> {
private Socket connection;
DaytimeTask(Socket connection) {
this.connection = connection;
}
public void call() {
try {
Writer out = new OutputStreamWriter(connection.getOutputStream());
Date now = new Date();
out.write(now.toString() +"\r\n");
out.flush();
} catch (IOException ex) {
System.err.println(ex);
} finally {
try {
connection.close();
} catch (IOException e) {
// ignore;
}
}
return null;
}
}
}
Echo Server
前述したように、クライアントから送信されたメッセージに従って応答する.
クライアントコード:
// . 문장을 입력하면 종료
import java.net.*;
import java.io.*;
public class EchoClient {
public static void main(String[] args) {
String hostname = "localhost";
if (args.length > 0) {
hostname = args[0];
}
PrintWriter networkOut = null;
BufferedReader networkIn = null;
try {
Socket theSocket = new Socket(hostname, 7);
networkIn = new BufferedReader(new InputStreamReader(theSocket.getInputStream()));
BufferedReader userIn = new BufferedReader(new InputStreamReader(System.in));
networkOut = new PrintWriter(theSocket.getOutputStream());
System.out.println("Connected to echo server");
while (true) {
String theLine = userIn.readLine();
if (theLine.equals(".")) break;
networkOut.println(theLine);
networkOut.flush();
System.out.println(networkIn.readLine());
}
} // end try
catch (IOException ex) {
System.err.println(ex);
}
finally {
try {
if (networkIn != null) networkIn.close();
if (networkOut != null) networkOut.close();
}
catch (IOException ex) {}
}
} // end main
} // end EchoClient
Networkin:サーバからデータを受信するストリームネットワーク出力:サーバからデータを送信するストリームuserin:ユーザからサーバにメッセージを受信するストリームtryブロックとfinallyブロックは別々のブロックである.2つのブロックで変数を共有するには、ブロックから除外して宣言する必要があります。この番組の次の部分はここに相当します。BufferedReader networkIn=null;PrintWriter networkOut=null;Ecoサーバはクライアントから受信したデータをクライアントに直接送信する.したがって、通常の場合、PrintWriterやReadLine()など、正常な処理が期待できない機能を使用してもよい。Networkinnの現在のDefault Encodeはオペレーティングシステムの基本的な符号化方法である。
Echo Server
クライアントがメッセージを送信するまで、サーバはクライアントにメッセージを送信しません。クライアントとサーバの間で送信および受信されるメッセージには、改行(改行)を含める必要があります。
ソケットはInputStream/OutputStreamを返しますが、InputStreamはInputStreamReader、BufferedReader、OutputStreamはPrintWriterに変換する必要があります。
送信側はPrintWriterのprintln()に送信され、受信側はBufferedReaderのreadlin()に読み出される。
行を開く
メッセージを受信するサーバまたはエンコードされたメッセージを受信するクライアントはreadline()に読み込まれるため、ローの末尾を識別する必要があります。送信者がメッセージの末尾に開文字を含める場合はprintln(msg)またはwrite(msg+"rn")で出力する必要があります。
readLine()メソッドは、書き換え文字を削除してデータを取得するので、そのデータを返しても書き換え文字を再追加する必要があります。
ネットワークプログラムからマルチバイトデータを出力するとflush()を呼び出す必要があります。
サーバ・オペレータが接続しているリモート・クライアントが誰であるかを通知するには、次のコードが必要です。InetAddress inetaddr = sock.getInetAddress(); System.out.println(「クライアント:」+inetaddr.getHostAddress();
クライアントが接続を閉じると、BufferedReaderのreadline()はnullを返します。
クライアントが異常に終了した場合、サーバのクライアント相対コードも終了する必要があります。
クライアント"."終了セクションをexit文に変更すると、クライアントは終了できますが、サーバは終了しません。
例)1つのクライアントのみにサービスし、実行中のEcoサーバを終了する
// . 문장을 입력하면 종료
import java.net.*;
import java.io.*;
public class EchoClient {
public static void main(String[] args) {
String hostname = "localhost";
if (args.length > 0) {
hostname = args[0];
}
PrintWriter networkOut = null;
BufferedReader networkIn = null;
try {
Socket theSocket = new Socket(hostname, 7);
networkIn = new BufferedReader(new InputStreamReader(theSocket.getInputStream()));
BufferedReader userIn = new BufferedReader(new InputStreamReader(System.in));
networkOut = new PrintWriter(theSocket.getOutputStream());
System.out.println("Connected to echo server");
while (true) {
String theLine = userIn.readLine();
if (theLine.equals(".")) break;
networkOut.println(theLine);
networkOut.flush();
System.out.println(networkIn.readLine());
}
} // end try
catch (IOException ex) {
System.err.println(ex);
}
finally {
try {
if (networkIn != null) networkIn.close();
if (networkOut != null) networkOut.close();
}
catch (IOException ex) {}
}
} // end main
} // end EchoClient
複数のクライアントを順番に処理するサーバ
ただし、別のクライアントにサービスを提供するには、1つのクライアントのサービスを終了する必要があります.import java.net.*;
import java.io.*;
public class EchoServer2 {
public static void main(String[] args) {
try {
ServerSocket server = new ServerSocket(7);
while (true) {
System.out.println("에코 서버가 접속을 기다립니다.");
Socket sock = server.accept();
System.out.println(sock.getInetAddress() + "- port" + sock.getPort() + " 이 접속하였습니다.");
BufferedReader br = new BufferedReader(new InputStreamReader(sock.getInputStream()));
PrintWriter pw = new PrintWriter(new OutputStreamWriter(sock.getOutputStream()));
String line = null;
line = br.readLine();
while (line != null) {
System.out.println("클라이언트로 부터 전송 받은 문자열 : " + line);
pw.println(line);
pw.flush();
line = br.readLine();
}
System.out.println("입출력 완료, 클라이언트와의 스트림 및 소켓 닫기");
pw.close();
br.close();
try {
if(sock != null)
sock.close();
}
catch(IOException e) {
}
}
} catch (Exception e) {
System.out.println(e);
}
} // main
}
マルチスレッドに変更するには?
新規入出力(NIO)を使用したEcoサーバ
普通のIOとは少し違います.import java.nio.*;
import java.nio.channels.*;
import java.net.*;
import java.util.*;
import java.io.IOException;
public class EchoServer9_5 {
public static int DEFAULT_PORT = 7;
public static void main(String[] args) {
int port;
try {
port = Integer.parseInt(args[0]);
} catch (RuntimeException ex) {
port = DEFAULT_PORT;
}
System.out.println("Listening for connections on port " + port);
ServerSocketChannel serverChannel;
Selector selector;
try {
serverChannel = ServerSocketChannel.open();
ServerSocket ss = serverChannel.socket();
InetSocketAddress address = new InetSocketAddress(port);
ss.bind(address);
serverChannel.configureBlocking(false);
selector = Selector.open();
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
} catch (IOException ex) {
ex.printStackTrace();
return;
}
while (true) {
try {
selector.select();
} catch (IOException ex) {
ex.printStackTrace();
break;
}
Set<SelectionKey> readyKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = readyKeys.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
iterator.remove();
try {
if (key.isAcceptable()) {
ServerSocketChannel server = (ServerSocketChannel) key.channel();
SocketChannel client = server.accept();
System.out.println("Accepted connection from " + client);
client.configureBlocking(false);
SelectionKey clientKey = client.register(
selector, SelectionKey.OP_WRITE | SelectionKey.OP_READ);
ByteBuffer buffer = ByteBuffer.allocate(100);
clientKey.attach(buffer);
}
if (key.isReadable()) {
SocketChannel client = (SocketChannel) key.channel();
ByteBuffer output = (ByteBuffer) key.attachment();
client.read(output);
}
if (key.isWritable()) {
SocketChannel client = (SocketChannel) key.channel();
ByteBuffer output = (ByteBuffer) key.attachment();
output.flip();
client.write(output);
output.compact();
}
} catch (IOException ex) {
key.cancel();
try {
key.channel().close();
} catch (IOException cex) {}
}
}
}
}
}
public void close() throws IOException
最後のソケットの使用が完了すると、サーバソケットを閉じるには、サーバソケットオブジェクトのclose()メソッドを呼び出す必要があります.
他のサーバがバインドできるように、占有しているポートを返します.
サーバソケットのaccept()で開いているすべてのソケットも削除
サーバースロットをオフにする必要がありますか?
プログラム終了後自動クローズ
関連メソッド
public boolean isClosed()
public boolean isBound()
isBound()は、サーバソケットが閉じていてもtrueを返します。
サーバーソケットが接続されているかどうかを確認するには、次の手順に従います.public static boolean isOpen()(ServerSocket ss){
return ss.isBound() && ! ss.isClosed();
}
Reference
この問題について(Java Network Programming_Server socket), 我々は、より多くの情報をここで見つけました
https://velog.io/@1984/Java-Network-ProgrammingServer-socket
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
import java.net.*;
import java.io.*;
import java.util.Date;
public class DaytimeServer {
public final static int PORT = 13;
public static void main(String[] args) {
try (ServerSocket server = new ServerSocket(PORT)) {
while (true) {
try (Socket connection = server.accept()) {
Writer out = new OutputStreamWriter(connection.getOutputStream());
Date now = new Date();
out.write(now.toString() +"\r\n");
out.flush();
connection.close();
} catch (IOException ex) {}
}
} catch (IOException ex) {
System.err.println(ex);
}
}
}
import java.io.*;
import java.net.*;
public class FriendServer {
public static void main(String[] args) {
Socket socket = null;
InputStreamReader isr = null;
OutputStreamWriter osw = null;
StringBuilder message = null;
try (ServerSocket serverSocket = new ServerSocket(7009);) {
System.out.println("-- 서버가 접속을 기다린다 -- ");
socket = serverSocket.accept();
System.out.println("-- 클라이언트와 접속 성공 -- ");
// Message from Client to Server
isr = new InputStreamReader(
socket.getInputStream(), "MS949");
message = new StringBuilder();
for (int c = isr.read(); c != -1; c = isr.read()) {
message.append((char) c);
}
socket.shutdownInput();
System.out.println("클라이언트 친구로부터 받은 메세지 : " + message);
// Message from Server to Client
osw = new OutputStreamWriter(
socket.getOutputStream() );
osw.write("나 9시에 갈 예정이야" + "\r\n");
System.out.println("클라이언트 친구에게 메시지를 보내다");
osw.flush();
socket.shutdownOutput();
osw.close();
isr.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
import java.io.*;
import java.net.*;
public class FriendClient {
public static void main(String[] args) {
InputStreamReader isr = null;
OutputStreamWriter osw = null;
StringBuilder reply = null;
try (Socket socket = new Socket("localhost", 7009)) {
socket.setSoTimeout(2000);
// Message from Client to Server
osw = new OutputStreamWriter(
socket.getOutputStream() );
osw.write("내일 학교에 몇 시에 올래" + "\r\n");
System.out.println("서버 친구에게 메시지를 보내다");
osw.flush();
socket.shutdownOutput();
// Message from Server to Client
isr = new InputStreamReader(
socket.getInputStream(), "MS949");
reply = new StringBuilder();
for (int c = isr.read(); c != -1; c = isr.read()) {
reply.append((char) c);
}
System.out.println("서버 친구로부터 받은 메세지 : " + reply);
osw.close();
isr.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
サーバは1つのリクエストのみを処理できません.
import java.net.*;
import java.io.*;
import java.util.Date;
public class MultithreadedDaytimeServer {
public final static int PORT = 13;
public static void main(String[] args) {
try (ServerSocket server = new ServerSocket(PORT)) {
while (true) {
try {
Socket connection = server.accept();
Thread task = new DaytimeThread(connection);
task.start();
} catch (IOException ex) {}
}
} catch (IOException ex) {
System.err.println("Couldn't start server");
}
}
private static class DaytimeThread extends Thread {
private Socket connection;
DaytimeThread(Socket connection) {
this.connection = connection;
}
public void run() {
try {
Writer out = new OutputStreamWriter(connection.getOutputStream());
Date now = new Date();
out.write(now.toString() +"\r\n");
out.flush();
} catch (IOException ex) {
System.err.println(ex);
} finally {
try {
connection.close();
} catch (IOException e) {
// ignore;
}
}
}
}
}
socket値を返します。
#+Threadpoolを使用したサーバ
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.*;
public class PooledDaytimeServer {
public final static int PORT = 13;
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(50);
try (ServerSocket server = new ServerSocket(PORT)) {
while (true) {
try {
Socket connection = server.accept();
Callable<Void> task = new DaytimeTask(connection);
pool.submit(task);
} catch (IOException ex) {}
}
} catch (IOException ex) {
System.err.println("Couldn't start server");
}
}
private static class DaytimeTask implements Callable<Void> {
private Socket connection;
DaytimeTask(Socket connection) {
this.connection = connection;
}
public void call() {
try {
Writer out = new OutputStreamWriter(connection.getOutputStream());
Date now = new Date();
out.write(now.toString() +"\r\n");
out.flush();
} catch (IOException ex) {
System.err.println(ex);
} finally {
try {
connection.close();
} catch (IOException e) {
// ignore;
}
}
return null;
}
}
}
Echo Server
前述したように、クライアントから送信されたメッセージに従って応答する.
クライアントコード:
// . 문장을 입력하면 종료
import java.net.*;
import java.io.*;
public class EchoClient {
public static void main(String[] args) {
String hostname = "localhost";
if (args.length > 0) {
hostname = args[0];
}
PrintWriter networkOut = null;
BufferedReader networkIn = null;
try {
Socket theSocket = new Socket(hostname, 7);
networkIn = new BufferedReader(new InputStreamReader(theSocket.getInputStream()));
BufferedReader userIn = new BufferedReader(new InputStreamReader(System.in));
networkOut = new PrintWriter(theSocket.getOutputStream());
System.out.println("Connected to echo server");
while (true) {
String theLine = userIn.readLine();
if (theLine.equals(".")) break;
networkOut.println(theLine);
networkOut.flush();
System.out.println(networkIn.readLine());
}
} // end try
catch (IOException ex) {
System.err.println(ex);
}
finally {
try {
if (networkIn != null) networkIn.close();
if (networkOut != null) networkOut.close();
}
catch (IOException ex) {}
}
} // end main
} // end EchoClient
Networkin:サーバからデータを受信するストリームネットワーク出力:サーバからデータを送信するストリームuserin:ユーザからサーバにメッセージを受信するストリームtryブロックとfinallyブロックは別々のブロックである.2つのブロックで変数を共有するには、ブロックから除外して宣言する必要があります。この番組の次の部分はここに相当します。BufferedReader networkIn=null;PrintWriter networkOut=null;Ecoサーバはクライアントから受信したデータをクライアントに直接送信する.したがって、通常の場合、PrintWriterやReadLine()など、正常な処理が期待できない機能を使用してもよい。Networkinnの現在のDefault Encodeはオペレーティングシステムの基本的な符号化方法である。
Echo Server
クライアントがメッセージを送信するまで、サーバはクライアントにメッセージを送信しません。クライアントとサーバの間で送信および受信されるメッセージには、改行(改行)を含める必要があります。
ソケットはInputStream/OutputStreamを返しますが、InputStreamはInputStreamReader、BufferedReader、OutputStreamはPrintWriterに変換する必要があります。
送信側はPrintWriterのprintln()に送信され、受信側はBufferedReaderのreadlin()に読み出される。
行を開く
メッセージを受信するサーバまたはエンコードされたメッセージを受信するクライアントはreadline()に読み込まれるため、ローの末尾を識別する必要があります。送信者がメッセージの末尾に開文字を含める場合はprintln(msg)またはwrite(msg+"rn")で出力する必要があります。
readLine()メソッドは、書き換え文字を削除してデータを取得するので、そのデータを返しても書き換え文字を再追加する必要があります。
ネットワークプログラムからマルチバイトデータを出力するとflush()を呼び出す必要があります。
サーバ・オペレータが接続しているリモート・クライアントが誰であるかを通知するには、次のコードが必要です。InetAddress inetaddr = sock.getInetAddress(); System.out.println(「クライアント:」+inetaddr.getHostAddress();
クライアントが接続を閉じると、BufferedReaderのreadline()はnullを返します。
クライアントが異常に終了した場合、サーバのクライアント相対コードも終了する必要があります。
クライアント"."終了セクションをexit文に変更すると、クライアントは終了できますが、サーバは終了しません。
例)1つのクライアントのみにサービスし、実行中のEcoサーバを終了する
// . 문장을 입력하면 종료
import java.net.*;
import java.io.*;
public class EchoClient {
public static void main(String[] args) {
String hostname = "localhost";
if (args.length > 0) {
hostname = args[0];
}
PrintWriter networkOut = null;
BufferedReader networkIn = null;
try {
Socket theSocket = new Socket(hostname, 7);
networkIn = new BufferedReader(new InputStreamReader(theSocket.getInputStream()));
BufferedReader userIn = new BufferedReader(new InputStreamReader(System.in));
networkOut = new PrintWriter(theSocket.getOutputStream());
System.out.println("Connected to echo server");
while (true) {
String theLine = userIn.readLine();
if (theLine.equals(".")) break;
networkOut.println(theLine);
networkOut.flush();
System.out.println(networkIn.readLine());
}
} // end try
catch (IOException ex) {
System.err.println(ex);
}
finally {
try {
if (networkIn != null) networkIn.close();
if (networkOut != null) networkOut.close();
}
catch (IOException ex) {}
}
} // end main
} // end EchoClient
複数のクライアントを順番に処理するサーバ
ただし、別のクライアントにサービスを提供するには、1つのクライアントのサービスを終了する必要があります.import java.net.*;
import java.io.*;
public class EchoServer2 {
public static void main(String[] args) {
try {
ServerSocket server = new ServerSocket(7);
while (true) {
System.out.println("에코 서버가 접속을 기다립니다.");
Socket sock = server.accept();
System.out.println(sock.getInetAddress() + "- port" + sock.getPort() + " 이 접속하였습니다.");
BufferedReader br = new BufferedReader(new InputStreamReader(sock.getInputStream()));
PrintWriter pw = new PrintWriter(new OutputStreamWriter(sock.getOutputStream()));
String line = null;
line = br.readLine();
while (line != null) {
System.out.println("클라이언트로 부터 전송 받은 문자열 : " + line);
pw.println(line);
pw.flush();
line = br.readLine();
}
System.out.println("입출력 완료, 클라이언트와의 스트림 및 소켓 닫기");
pw.close();
br.close();
try {
if(sock != null)
sock.close();
}
catch(IOException e) {
}
}
} catch (Exception e) {
System.out.println(e);
}
} // main
}
マルチスレッドに変更するには?
新規入出力(NIO)を使用したEcoサーバ
普通のIOとは少し違います.import java.nio.*;
import java.nio.channels.*;
import java.net.*;
import java.util.*;
import java.io.IOException;
public class EchoServer9_5 {
public static int DEFAULT_PORT = 7;
public static void main(String[] args) {
int port;
try {
port = Integer.parseInt(args[0]);
} catch (RuntimeException ex) {
port = DEFAULT_PORT;
}
System.out.println("Listening for connections on port " + port);
ServerSocketChannel serverChannel;
Selector selector;
try {
serverChannel = ServerSocketChannel.open();
ServerSocket ss = serverChannel.socket();
InetSocketAddress address = new InetSocketAddress(port);
ss.bind(address);
serverChannel.configureBlocking(false);
selector = Selector.open();
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
} catch (IOException ex) {
ex.printStackTrace();
return;
}
while (true) {
try {
selector.select();
} catch (IOException ex) {
ex.printStackTrace();
break;
}
Set<SelectionKey> readyKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = readyKeys.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
iterator.remove();
try {
if (key.isAcceptable()) {
ServerSocketChannel server = (ServerSocketChannel) key.channel();
SocketChannel client = server.accept();
System.out.println("Accepted connection from " + client);
client.configureBlocking(false);
SelectionKey clientKey = client.register(
selector, SelectionKey.OP_WRITE | SelectionKey.OP_READ);
ByteBuffer buffer = ByteBuffer.allocate(100);
clientKey.attach(buffer);
}
if (key.isReadable()) {
SocketChannel client = (SocketChannel) key.channel();
ByteBuffer output = (ByteBuffer) key.attachment();
client.read(output);
}
if (key.isWritable()) {
SocketChannel client = (SocketChannel) key.channel();
ByteBuffer output = (ByteBuffer) key.attachment();
output.flip();
client.write(output);
output.compact();
}
} catch (IOException ex) {
key.cancel();
try {
key.channel().close();
} catch (IOException cex) {}
}
}
}
}
}
public void close() throws IOException
最後のソケットの使用が完了すると、サーバソケットを閉じるには、サーバソケットオブジェクトのclose()メソッドを呼び出す必要があります.
他のサーバがバインドできるように、占有しているポートを返します.
サーバソケットのaccept()で開いているすべてのソケットも削除
サーバースロットをオフにする必要がありますか?
プログラム終了後自動クローズ
関連メソッド
public boolean isClosed()
public boolean isBound()
isBound()は、サーバソケットが閉じていてもtrueを返します。
サーバーソケットが接続されているかどうかを確認するには、次の手順に従います.public static boolean isOpen()(ServerSocket ss){
return ss.isBound() && ! ss.isClosed();
}
Reference
この問題について(Java Network Programming_Server socket), 我々は、より多くの情報をここで見つけました
https://velog.io/@1984/Java-Network-ProgrammingServer-socket
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
// . 문장을 입력하면 종료
import java.net.*;
import java.io.*;
public class EchoClient {
public static void main(String[] args) {
String hostname = "localhost";
if (args.length > 0) {
hostname = args[0];
}
PrintWriter networkOut = null;
BufferedReader networkIn = null;
try {
Socket theSocket = new Socket(hostname, 7);
networkIn = new BufferedReader(new InputStreamReader(theSocket.getInputStream()));
BufferedReader userIn = new BufferedReader(new InputStreamReader(System.in));
networkOut = new PrintWriter(theSocket.getOutputStream());
System.out.println("Connected to echo server");
while (true) {
String theLine = userIn.readLine();
if (theLine.equals(".")) break;
networkOut.println(theLine);
networkOut.flush();
System.out.println(networkIn.readLine());
}
} // end try
catch (IOException ex) {
System.err.println(ex);
}
finally {
try {
if (networkIn != null) networkIn.close();
if (networkOut != null) networkOut.close();
}
catch (IOException ex) {}
}
} // end main
} // end EchoClient
クライアントがメッセージを送信するまで、サーバはクライアントにメッセージを送信しません。クライアントとサーバの間で送信および受信されるメッセージには、改行(改行)を含める必要があります。
ソケットはInputStream/OutputStreamを返しますが、InputStreamはInputStreamReader、BufferedReader、OutputStreamはPrintWriterに変換する必要があります。
送信側はPrintWriterのprintln()に送信され、受信側はBufferedReaderのreadlin()に読み出される。
行を開く
メッセージを受信するサーバまたはエンコードされたメッセージを受信するクライアントはreadline()に読み込まれるため、ローの末尾を識別する必要があります。送信者がメッセージの末尾に開文字を含める場合はprintln(msg)またはwrite(msg+"rn")で出力する必要があります。
readLine()メソッドは、書き換え文字を削除してデータを取得するので、そのデータを返しても書き換え文字を再追加する必要があります。
ネットワークプログラムからマルチバイトデータを出力するとflush()を呼び出す必要があります。
サーバ・オペレータが接続しているリモート・クライアントが誰であるかを通知するには、次のコードが必要です。InetAddress inetaddr = sock.getInetAddress(); System.out.println(「クライアント:」+inetaddr.getHostAddress();
クライアントが接続を閉じると、BufferedReaderのreadline()はnullを返します。
クライアントが異常に終了した場合、サーバのクライアント相対コードも終了する必要があります。
クライアント"."終了セクションをexit文に変更すると、クライアントは終了できますが、サーバは終了しません。
例)1つのクライアントのみにサービスし、実行中のEcoサーバを終了する
// . 문장을 입력하면 종료
import java.net.*;
import java.io.*;
public class EchoClient {
public static void main(String[] args) {
String hostname = "localhost";
if (args.length > 0) {
hostname = args[0];
}
PrintWriter networkOut = null;
BufferedReader networkIn = null;
try {
Socket theSocket = new Socket(hostname, 7);
networkIn = new BufferedReader(new InputStreamReader(theSocket.getInputStream()));
BufferedReader userIn = new BufferedReader(new InputStreamReader(System.in));
networkOut = new PrintWriter(theSocket.getOutputStream());
System.out.println("Connected to echo server");
while (true) {
String theLine = userIn.readLine();
if (theLine.equals(".")) break;
networkOut.println(theLine);
networkOut.flush();
System.out.println(networkIn.readLine());
}
} // end try
catch (IOException ex) {
System.err.println(ex);
}
finally {
try {
if (networkIn != null) networkIn.close();
if (networkOut != null) networkOut.close();
}
catch (IOException ex) {}
}
} // end main
} // end EchoClient
複数のクライアントを順番に処理するサーバ
ただし、別のクライアントにサービスを提供するには、1つのクライアントのサービスを終了する必要があります.
import java.net.*;
import java.io.*;
public class EchoServer2 {
public static void main(String[] args) {
try {
ServerSocket server = new ServerSocket(7);
while (true) {
System.out.println("에코 서버가 접속을 기다립니다.");
Socket sock = server.accept();
System.out.println(sock.getInetAddress() + "- port" + sock.getPort() + " 이 접속하였습니다.");
BufferedReader br = new BufferedReader(new InputStreamReader(sock.getInputStream()));
PrintWriter pw = new PrintWriter(new OutputStreamWriter(sock.getOutputStream()));
String line = null;
line = br.readLine();
while (line != null) {
System.out.println("클라이언트로 부터 전송 받은 문자열 : " + line);
pw.println(line);
pw.flush();
line = br.readLine();
}
System.out.println("입출력 완료, 클라이언트와의 스트림 및 소켓 닫기");
pw.close();
br.close();
try {
if(sock != null)
sock.close();
}
catch(IOException e) {
}
}
} catch (Exception e) {
System.out.println(e);
}
} // main
}
マルチスレッドに変更するには?
新規入出力(NIO)を使用したEcoサーバ
普通のIOとは少し違います.
import java.nio.*;
import java.nio.channels.*;
import java.net.*;
import java.util.*;
import java.io.IOException;
public class EchoServer9_5 {
public static int DEFAULT_PORT = 7;
public static void main(String[] args) {
int port;
try {
port = Integer.parseInt(args[0]);
} catch (RuntimeException ex) {
port = DEFAULT_PORT;
}
System.out.println("Listening for connections on port " + port);
ServerSocketChannel serverChannel;
Selector selector;
try {
serverChannel = ServerSocketChannel.open();
ServerSocket ss = serverChannel.socket();
InetSocketAddress address = new InetSocketAddress(port);
ss.bind(address);
serverChannel.configureBlocking(false);
selector = Selector.open();
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
} catch (IOException ex) {
ex.printStackTrace();
return;
}
while (true) {
try {
selector.select();
} catch (IOException ex) {
ex.printStackTrace();
break;
}
Set<SelectionKey> readyKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = readyKeys.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
iterator.remove();
try {
if (key.isAcceptable()) {
ServerSocketChannel server = (ServerSocketChannel) key.channel();
SocketChannel client = server.accept();
System.out.println("Accepted connection from " + client);
client.configureBlocking(false);
SelectionKey clientKey = client.register(
selector, SelectionKey.OP_WRITE | SelectionKey.OP_READ);
ByteBuffer buffer = ByteBuffer.allocate(100);
clientKey.attach(buffer);
}
if (key.isReadable()) {
SocketChannel client = (SocketChannel) key.channel();
ByteBuffer output = (ByteBuffer) key.attachment();
client.read(output);
}
if (key.isWritable()) {
SocketChannel client = (SocketChannel) key.channel();
ByteBuffer output = (ByteBuffer) key.attachment();
output.flip();
client.write(output);
output.compact();
}
} catch (IOException ex) {
key.cancel();
try {
key.channel().close();
} catch (IOException cex) {}
}
}
}
}
}
public void close() throws IOException
最後のソケットの使用が完了すると、サーバソケットを閉じるには、サーバソケットオブジェクトのclose()メソッドを呼び出す必要があります.
他のサーバがバインドできるように、占有しているポートを返します.
サーバソケットのaccept()で開いているすべてのソケットも削除
サーバースロットをオフにする必要がありますか?
プログラム終了後自動クローズ
関連メソッド
public boolean isClosed()
public boolean isBound()
isBound()は、サーバソケットが閉じていてもtrueを返します。
サーバーソケットが接続されているかどうかを確認するには、次の手順に従います.
public static boolean isOpen()(ServerSocket ss){
return ss.isBound() && ! ss.isClosed();
}
Reference
この問題について(Java Network Programming_Server socket), 我々は、より多くの情報をここで見つけました https://velog.io/@1984/Java-Network-ProgrammingServer-socketテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol