先上最简单的使用demo,一个服务端和一个客户端
服务端:
package com.kangzye;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerMain {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(9090);
System.out.println("running ...");
boolean run = true;
int count = 1;
while(run){
Socket socket = serverSocket.accept();
System.out.print("[Main] Accepted:");
System.out.println(socket.getRemoteSocketAddress());
new Worker(socket, "worker_"+count).start();
count ++;
}
}
static class Worker extends Thread{
boolean running = true;
Socket socket = null;
String name;
public Worker(Socket socket,String workerName) {
this.socket = socket;
this.name = workerName;
Runtime.getRuntime().addShutdownHook(new Thread(){
@Override
public void run() {
System.out.println("shutdonw " + name);
running = false;
}
});
}
@Override
public void run() {
try {
InputStream in = socket.getInputStream();
int c = -1;
while(running && (c=in.read())!=-1){
System.out.print((char)c);
}
System.out.println(this.name+" terminated.");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
客户端:
package com.kangzye;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
public class ClientMain {
public static void main(String[] args) throws UnknownHostException, IOException {
String host = args[0];
int port = Integer.parseInt(args[1]);
//Socket socket = new Socket(host,port,InetAddress.getLocalHost(),50000); // #绑定本地50000端口出口
Socket socket = new Socket(host,port);
transformdata(socket);
}
static void transformdata(Socket socket) throws IOException{
OutputStream outputStream = socket.getOutputStream();
final BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));
new ConsoleInputer().work(new InputAble() {
@Override
public void inputed(String stream) {
System.out.println(stream);
try {
writer.write(stream);
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
static class ConsoleInputer{
void work(InputAble ia){
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String line = null;
try {
while((line=reader.readLine())!="bye"){
ia.inputed(line);
}
System.out.println("bye...");
} catch (IOException e) {
e.printStackTrace();
}
}
}
static interface InputAble{
void inputed(String stream);
}
}
服务单例子是接受多个 socket 连接请求,每个连接请求启用一个worker 去接收。
客户端可以自定自己的出口端口(通过注释掉的那行代码),但是服务端打印出来的接收的客户端的端口却不是50000 ,原因是 客户端机器是 通过路由上网,服务器端打印的客户端端口其实是 路由器 的出口端口号,这个是程序没有办法指定的(非要指定就登陆路由器进行路由的设置即可);
客户端 socket 在创建时可以不指定 地址和端口,而使用connect 方法来连接也可以。如下:
Socket socket = new Socket();
SocketAddress endpoint = new InetSocketAddress(host, port);
socket.connect(endpoint);