Javaの標準APIを使用して、TCPソケット経由でサーバーにリクエストを送信し、その応答データを取得する実装例を紹介します。コードは自己完結型で、初心者でも理解しやすいように設計されています。
Socketクライアントユーティリティクラス
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.net.*;
public class TcpSocketClient {
private static final Logger logger = LoggerFactory.getLogger(TcpSocketClient.class);
private static final String INVALID_ADDRESS = "ホストまたはポートが無効です: %s:%d";
private static final String NO_RESPONSE = "サーバーから応答がありません: %s:%d";
private static final String CONNECTION_FAILED = "接続に失敗しました。サーバーが稼働中か確認してください: %s:%d";
private static final String REQUEST_TIMEOUT = "リクエストがタイムアウトしました: %s:%d";
private static final String IO_ERROR = "I/Oエラーが発生しました: %s:%d";
public static SocketResult send(String host, int port) {
return send(host, port, null);
}
public static SocketResult send(String host, int port, byte[] payload) {
SocketResult result = new SocketResult();
result.setRequestData(payload);
if (StringUtils.isBlank(host) || port <= 0) {
result.setErrorMessage(String.format(INVALID_ADDRESS, host, port));
return result;
}
try (Socket socket = new Socket()) {
socket.connect(new InetSocketAddress(host, port), 5000);
socket.setSoTimeout(60000);
try (OutputStream out = socket.getOutputStream();
InputStream in = socket.getInputStream()) {
if (payload != null && payload.length > 0) {
out.write(payload);
out.flush();
}
socket.shutdownOutput();
result.setSent(true);
if (in != null) {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
byte[] readBuffer = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(readBuffer)) != -1) {
buffer.write(readBuffer, 0, bytesRead);
}
result.setResponseData(buffer.toByteArray());
} else {
result.setErrorMessage(String.format(NO_RESPONSE, host, port));
}
}
} catch (ConnectException e) {
result.setErrorMessage(String.format(CONNECTION_FAILED, host, port));
logger.error(result.getErrorMessage(), e);
} catch (SocketTimeoutException e) {
result.setSent(true);
result.setErrorMessage(String.format(REQUEST_TIMEOUT, host, port));
logger.error(result.getErrorMessage());
} catch (IOException e) {
result.setSent(true);
result.setErrorMessage(String.format(IO_ERROR, host, port));
logger.error(result.getErrorMessage(), e);
}
return result;
}
}
レスポンス結果を格納するDTOクラス
import java.io.Serializable;
public class SocketResult implements Serializable {
private static final long serialVersionUID = 1L;
private byte[] requestData;
private byte[] responseData;
private String errorMessage;
private boolean sent = false;
// Getters and Setters
public byte[] getRequestData() { return requestData; }
public void setRequestData(byte[] requestData) { this.requestData = requestData; }
public byte[] getResponseData() { return responseData; }
public void setResponseData(byte[] responseData) { this.responseData = responseData; }
public String getErrorMessage() { return errorMessage; }
public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; }
public boolean isSent() { return sent; }
public void setSent(boolean sent) { this.sent = sent; }
}
テスト用の簡易サーバー実装
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class MockSocketServer {
public static void main(String[] args) throws IOException {
try (ServerSocket server = new ServerSocket(15999)) {
System.out.println("サーバー起動: ポート15999で待機中...");
while (true) {
try (Socket client = server.accept();
InputStream input = client.getInputStream();
OutputStream output = client.getOutputStream()) {
System.out.println("クライアント接続を受信");
ByteArrayOutputStream received = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = input.read(buffer)) != -1) {
received.write(buffer, 0, len);
}
String requestText = new String(received.toByteArray(), "UTF-8");
System.out.println("受信メッセージ: " + requestText);
output.write("サーバーからの応答データ".getBytes("UTF-8"));
output.flush();
}
}
}
}
}
クライアント側のテストコード
public class SocketClientTest {
public static void main(String[] args) {
SocketResult result = TcpSocketClient.send("127.0.0.1", 15999, "クライアントからのリクエスト".getBytes());
if (result.getErrorMessage() != null) {
System.err.println("エラー: " + result.getErrorMessage());
} else {
System.out.println("受信応答: " + new String(result.getResponseData()));
}
}
}
上記のサーバーを先に起動し、その後クライアントを実行すると、双方向の通信が確認できます。タイムアウトや接続エラーなどの例外ケースも適切にハンドリングされています。