クラスライブラリjava.net.ServerSocketおよびjava.net.Socketを利用すると、サーバーサイドおよびクライアントサイドのTCP/IP通信が実装できます。一般にTCPは信頼性が高く通信のオーバーヘッドは大きいです。
クラスライブラリjava.net.DatagramSocketおよびjava.net.DatagramPacketを利用すると、サーバーサイドおよびクライアントサイドのUDP/IP通信が実装できます。一般にUDPは信頼性が低く通信のオーバーヘッドは小さいです。ビデオストリーミングなど、多少のパケットロスが問題にならない通信等で利用されます。
以下のサンプルプログラムでは、クライアントが送信した数値を受信したサーバーは、それを2乗してクライアントに返します。
Server.java
import java.net.ServerSocket;
import java.net.Socket;
import java.io.InputStream;
import java.io.DataInputStream;
import java.io.OutputStream;
import java.io.DataOutputStream;
class Server {
public static void main(String args[]) {
try {
int port = Integer.parseInt(args[0]); //サーバ側の待受ポート番号
ServerSocket ss = new ServerSocket(port);
while(true) {
Socket s = ss.accept(); //クライアントからの通信開始要求が来るまで待機
// 以下、クライアントからの要求発生後
InputStream is = s.getInputStream(); //クライアントから数値を受信
DataInputStream dis = new DataInputStream(is);
int req = dis.readInt();
OutputStream os = s.getOutputStream(); //二乗した結果を送信
DataOutputStream dos = new DataOutputStream(os);
dos.writeInt(req*req);
// ストリームを閉じる
dos.close();
dis.close();
}
}
catch(Exception e) {
System.out.println("Exception: " + e);
}
}
}
Client.java
import java.net.Socket;
import java.io.InputStream;
import java.io.DataInputStream;
import java.io.OutputStream;
import java.io.DataOutputStream;
class Client {
public static void main(String args[]) {
try {
String server = args[0];
int port = Integer.parseInt(args[1]); //サーバー側のポート番号
Socket s = new Socket(server, port);
// サーバーに数値を送信
OutputStream os = s.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeInt(Integer.parseInt(args[2]));
// 演算結果を受信
InputStream is = s.getInputStream();
DataInputStream dis = new DataInputStream(is);
int res = dis.readInt();
System.out.println(res);
// ストリームを閉じる
dis.close();
dos.close();
}
catch (Exception e) {
System.out.println("Exception: " + e);
}
}
}
サーバーサイド (2乗した結果を返します)
$ javac Server.java && java Server 8888
クライアントサイド
$ javac Client.java && java Client localhost 8888 7
49
クライアントから受信した文字列をサーバー側で表示します。
Server.java
import java.net.DatagramSocket;
import java.net.DatagramPacket;
class Server {
public static void main(String args[]) {
try {
int port = Integer.parseInt(args[0]); //サーバー側の待受ポート番号
DatagramSocket ds = new DatagramSocket(port);
byte buffer[] = new byte[32]; //受信データを書き込むためのバッファ
while(true) {
// 受信したデータは実際にはbufferに格納される
DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
ds.receive(dp); //受信するまで待機
// 以下、受信後
byte received[] = new byte[dp.getLength()];
byte tmp[] = dp.getData(); //32バイト (buffer.length)
for(int i=0; i<dp.getLength(); ++i) received[i]=tmp[i];
// 文字列化して出力
String str = new String(received);
System.out.println(str);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
Client.java
import java.net.DatagramSocket;
import java.net.DatagramPacket;
import java.net.InetAddress;
class Client {
public static void main(String args[]) {
try {
InetAddress addr = InetAddress.getByName(args[0]);
int port = Integer.parseInt(args[1]); //サーバ側の待受ポート番号
// 送信するパケットを生成
byte buffer[] = args[2].getBytes();
DatagramPacket dp = new DatagramPacket(buffer, buffer.length, addr, port);
// ソケットを生成してパケットを送信
DatagramSocket ds = new DatagramSocket();
ds.send(dp);
ds.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
サーバーサイド
$ javac Server.java && java Server 8888
qoosky
クライアントサイド
$ javac Client.java && java Client localhost 8888 qoosky