Socketプログラミングベース


1.javaの従来のTCP socketプログラミングはブロック方式であり、簡単なSocketプログラムの例は以下の通りである.
(1).サービス・エンド・プログラム:
import java.io.*;
import java.net.*;

public class SocketServer{
	public static final int PORT = 10500;
	public static void main(String[] args)throws IOException{
		// , ip 
		ServerSocket server = new ServerSocket(PORT);
		System.out.println(“Started:” + server);
		try{
			// 
	Socket socket = s.accept();
	try{
	System.out.println(“Connection accepted:” + socket);
	BufferedReader in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
				// PrintWriter
				PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())), true);
				while(true){
	String str = in.readLine();
	if(str.equals(“END”)) break;
	System.out.println(“Echoing:” + str);
	out.println(str);
}
}finally{
	System.out.println(“closing…”);
	socket.close();
}
}finally{
	server.close();
}
}
}

(2).クライアントプログラム:
import java.io.*;
import java.net.*;

public class SocketClient{
	public static void main(String[] args)throw IOException{
	// 127.0.0.1 , InetAddress.getByName(“localhost”)
	// InetAddress.getByName(“127.0.0.1”);
InetAddress addr = InetAddress.getByName(null);
System.out.println(“addr = ”+ addr);
Socket socket = new Socket(addr, SocketServer.PORT);
try{
	System.out.println(“socket = ” + socket);
	BufferedReader in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
			// PrintWriter
			PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())), true);
			for(int i = 0; i < 10; i++){
	out.println(“howdy ” + i);
	String str = in.readLine();
	System.out.println(str);
}
out.println(“END”);
}finally{
	System.out.println(“closing…”);
	socket.close();
}
}
}

Socket接続には、サービス側IPアドレス、サービス側ポート、クライアントIPアドレス、クライアント側ポートの4つの重要な情報が必要です.この4つの情報は、サービス側プログラムとクライアントプログラムが相互にインタラクティブになることができます.例えば、クライアント・プログラムのポートが12000の場合、
サービス側が印刷するSocket情報は次のとおりです.
Socket[addr=127.0.0.1,port=10200,localport=10500]
addrとportはクライアントのipとポートであり、localportはサービス側ポートである.
クライアントが印刷するSocket情報は次のとおりです.
Socket[addr=localhost/127.0.0.1,port=8080, localport=12000]
ここでaddrとportはクライアント接続のサービス側ipとポートであり、localportはクライアントポートである.
2.マルチサービスエンドマルチクライアントのSocketプログラム:
1の例サービス側は1つのクライアントプログラムにしかサービスできないが、複数のクライアントプログラムにサービスを提供するには、マルチスレッド方式でクライアント要求を処理しなければならない.例は以下の通りである.
(1).サービス・エンド・プログラム:
import java.io.*;
import java.net.*;

class SocketServer extends Thread{
	private Socket socket;
	private BufferedReader in;
	private PrintWriter out;
	public ServerSocket(Socket s)throws IOException{
	socket = s;
	in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
		// PrintWriter
		out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream())), true);
		start();
}
// 
public void run(){
	try{
	while(true){
	String str = in.readLine();
	if(str.equals(“END”)) break;
	System.out.println(“Echoing:” + str);
	out.println(str);
}
System.out.println(“closing…”);
}catch(IOException e){
	System.err.println(“IO Exception”);
}finally{
	try{
	socket.close();
} catch(IOException e){
	System.err.println(“Socket not closed”);
}
}
}
}
public class MultiServer{
	static final int PORT = 10500;
	public static void main(String[] args) throws IOException{
	ServerSocket server = new ServerSocket(PORT);
	System.out.println(“Server Started”);
	try{
	while(true){
	Socket s = server.accept();
	try{
		// 
	new SocketServer(s);
}catch(IOException e){
s.close();
}
}
}finally{
	server.close();
}
}
}

(2).クライアントプログラム:
import java.net.*;
import java.io.*;

class SocketClient extends Thread{
	private Socket socket;
	private BufferedReader in;
	private PrintWriter out;
	private static int counter = 0;
	private int id = counter++;
	private static int threadcount = 0;
	public int getThreadCount(){
	return threadcount;
}
public SocketClient(InetAddress addr){
	System.out.println(“Creating client:” + id);
	Threadcount++;
	try{
	socket = new Socket(addr, SocketServer.PORT);
}catch(IOException e){
	System.err.println(“Create socket failed”);
}
try{
	in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
			// PrintWriter
			out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream())), true);
			start();	
}catch(IOException e){
	try{
	socket.close();
}catch(IOException ex){
	System.err.println(“Socket not closed”);
}
}
}
// 
\public void run(){
	try{
	for(int i = 0; i < 25; i++){
		out.println(“Client ” + id + “ :” + i);
		String str = in.readLine();
		System.out.println(str);
}
out.println(“END”);
}catch(IOException e){
	System.err.println(“IO Exception”);
}finally{
	try{
	socket.close();
}catch(IOException e){
	System.err.println(“Socket not closed”);
}
threadcount--;
}
}
}
public class MultiClient{
	static final int MAX_THREADS = 40;
	public static void main(String[] args)throws IOException, InterruptedException{
		InetAddress addr = InetAddress.getByName(null);
		while(true){
	if(SocketClient. getThreadCount() < MAX_THREADS){
	// Socket 
	new SocketClient(addr);
	Thread.currentThread().sleep(1000); 
}
}
}

Socketクライアント・プログラムのポートはシステムによって割り当てられ、作成時に接続するターゲット・サービス・エンド・ポートを指定するだけでよい.
3.UDP Socketプログラミングの小例:
前の2つの例はTCPのsocketプログラミングであり、信頼性の要求が高くなく、速度の要求が高い場合、UDPを使用する必要があり、UDPの例プログラムは以下の通りである.
(1).サービス・エンド・プログラム:
import java.net.*;

public class UDPServer{
	private static final int SERVER_PORT = 5000;
	private DatagramSocket dataSocket;
	private DatagramPacket dataPacket;
	private byte receiveByte[];
	private String receiveStr;
	public static void main(String[] args){
	try{
	dataSocket = new DatagramSocket(SERVER_PORT);
	receiveByte = new byte[1024];
	dataPacket = new DatagramPacket(receiveByte, receiveByte.length);
	receiveStr = “”;
	int i = 0;
	while(i == 0){
		// 
	dataSocket.receive(dataPacket);
	i = dataPacket.getLength();
	if(i > 0){
	receiveStr = new String(receiveByte, 0, dataPacket.getLength());
	System.out.println(receiveStr);
	// 
	i = 0;
}
}
}catch(Exception e){
	e.printStackTrace();
}
}
}

(2).クライアントプログラム:
import java.io.*;
import java.net.*;

public class UDPClient{
	private static final int CLIENT_PORT = 5001;
	private DatagramSocket dataSocket;
	private DatagramPacket dataPacket;
	private byte sendDataByte[];
	private String sendStr;
	public static void main(String[] args){
		try{
	dataSocket = new DatagramSocket(CLIENT_PORT);
	sendDataByte = new byte[1024];
	sendStr = “UDP ”;
	sendDataByte = sendStr.getBytes();
	// : 
dataPacket = new DatagramPacket(sendDataByte, sendDataByte.length, 
		InetAddress.getByName(“localhost”), UDPServer.SERVER_PORT);
dataSocket.send(dataPacket);
}catch(SocketExcption se){
	se.printStackTrace();
} catch(IOExcption ie){
	ie.printStackTrace();
}
}
}

DatagramSocketは、UDPパケットを送信および受信するためのソケットであり、DatagramPacketは、UDPを表すためのパケットである.UDP通信には厳密な意味でのサービス側とクライアントは存在せず、各プログラムはサービス側であってもよいし、同時にクライアントであってもよいし、P 2 P対等な通信を実現することができる.