java实现一个简单的网络聊天程序

代码

服务器端

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+HCtrl+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也都有着类似的对应关系,通过查看调用栈可以一一查找,这里不再赘述

posted @ 2019-12-08 16:43  yorkiii  阅读(1239)  评论(0编辑  收藏  举报
Language: HTML