代码
服务器端
package socket_demo;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class server {
public static void main(String[] args) throws Exception {
// 监听指定的端口,阻塞直至客户端连接此端口
int port = 23333;
ServerSocket server = new ServerSocket(port);
System.out.println("server is waiting...");
Socket socket = server.accept();
System.out.println("Connected!");
// 读取从客户端返回的输入流,至尾端时返回-1
InputStream input = socket.getInputStream();
byte[] bytes = new byte[1024];
int len;
StringBuilder get = new StringBuilder();
while ((len = input.read(bytes)) != -1) {
get.append(new String(bytes, 0, len, "UTF-8"));
}
System.out.println("get message from client: " + get);
OutputStream output = socket.getOutputStream();
String sent = "Hi there";
output.write(sent.getBytes("UTF-8"));
System.out.println("sent message to client: " + sent);
// 关闭socket与服务器端
input.close();
output.close();
socket.close();
server.close();
}
}
客户端
package socket_demo;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class client {
public static void main(String args[]) throws Exception {
// 连接本地主机,端口自设,与服务端一致即可
String host = "127.0.0.1";
int port = 23333;
// 通过socket与服务端建立连接
Socket socket = new Socket(host, port);
if(socket.isConnected()){
System.out.println("Connected!");
}
// 将要发送的信息写入输出流
OutputStream output = socket.getOutputStream();
String sent = "hello";
socket.getOutputStream().write(sent.getBytes("UTF-8"));
// 关闭客户端的输出流(单向,并未关闭socket)
socket.shutdownOutput();
System.out.println("sent message to server: " + sent);
// 读取从server返回的输入流
InputStream input = socket.getInputStream();
byte[] bytes = new byte[1024];
int len;
StringBuilder get = new StringBuilder();
while ((len = input.read(bytes)) != -1) {
get.append(new String(bytes, 0, len,"UTF-8"));
}
System.out.println("get message from server: " + get);
// 关闭socket
input.close();
output.close();
socket.close();
}
}
测试结果
服务器端
客户端
JAVA Socket API分析
以上代码用到的JAVA SOCKET API主要有:
Socket(InetAddress address, int port)
--创建一个流套接字并将其连接到指定的IP地址与指定端口
ServerSocket(int port)
--服务器端绑定一个窗口
server.accept()
--服务器端等待连接(持续阻塞)
socket.getInputStream()
--返回此套接字的输入流
socket.getOutputStream()
--返回此套接字的输出流
socket.close()
--关闭此套接字
JAVA中方法的实现都要通过JVM翻译给系统执行,所以JAVA SOCKET API与系统(本例为windows)SOCKET API有着对应关系。
我们通过在IDEA中使用Ctrl+Alt+H
与Ctrl+Alt+B
跟踪查看api的调用栈,以server.accept()
为例
双击右边函数名,查看其调用,进一步查看ServerSocket.implAccept(Socket)
这里accept0()
是一个native api,无法再继续上溯
完整的调用栈为server.accept()
->ServerSocket.implAccept(Socket) (java.net)
->SocketImpl.accept(SocketImpl)
->AbstractPlainSocketImpl.socketAccept(SocketImpl)
->PlainSocketImpl.accept0(int, InetSocketAddress[])
综上,java socket中的server.accept()
对应windows socket中的accept0(int var0, InetSocketAddress[] var1)
其它socket api也都有着类似的对应关系,通过查看调用栈可以一一查找,这里不再赘述