1.Tcp概念
通信的两端通过创建Socket对象实现通信,严格区分客户端和服务端,必须是由客户端去联系服务端才能建立通信,服务端不可以主动连接客户端,且服务daunt需要先启动,等待客户端的连接。
JDK提供了两个类用于实现TCP程序,分别为ServerSocket用于服务端和Socket用于客户端。通信时,首先创建一个服务端的ServerSocket对象,相当于开启一个服务,等待客户端的连接,然后创建代表客户端的Socket对象向服务端发出连接请求,服务器端响应请求,两者建立连接并开始通信。
2.Java中提供的类
ServerSocket(服务端):ServerSocket对象负责监听某台计算机的某个端口号,创建ServerSocket对象后,需要继续调用该对象的accept()方法,接收来自客户端的请求,当执行了accept()方法后,服务端会发生阻塞,直到客户端发出连接请求,accept()方法才会返回一个Socket对象用于和客户端实现通信,程序才能继续执行。
构造方法:
(1) ServerSocket():创建ServerSocket对象并没有绑定端口号。这样的对象创建的服务器没有监听任何端口,不能直接使用,需要继续使用bind(SocketAddress endpoint)方法将其绑定到指定端口上才可以正常使用;
(2) ServerSocket(int port):创建ServerSocket对象时将其绑定到指定的一个端口号上(参数port为端口号),端口号可以指定为0,此时系统就会分配一个还没有被其他网络程序所使用的端口,由于客户端需要根据指定端口号来访问服务端程序,所以端口号随机的情况并不常用,通常是指定一个特定端口。
(3) ServerSocket(int port ,int backlog): backlog参数代表在服务器忙时,可以与之保持连接请求的等待客户数量,未指定默认值为50.
(4) ServerSocket(int port ,int backlog,InetAddress bindAddr): bindAddr代表相关IP地址信息,适用于计算机上有多块网卡和多个IP的情况,我们可以明确规定ServerSocket在哪块网卡或IP地址上等待客户连接请求,显然,对于一般只有一块网卡的情况,就不用专门的指定了。
其他方法:
(1)Socket accept():等待客户端连接,在客户端连接前一直处于阻塞状态,如果有客户端进行连接会返回一个与之对应的Socket对象;
(2) InetAddress getInetAddress():返回一个InetAddress对象,该对象中封装了ServerSocket绑定的IP地址;
(3)Boolean isClose():判断ServerSocket对象是否为关闭状态,如果是关闭状态则返回true,否则返回false;
(4)void bind(SocketAddress endpoint):该方法用于将ServerSocket对象绑定到指定的IP地址和端口号,其中参数endpoint封装了IP地址和端口号。
Socket(客户端):
构造方法:
(1) Socket():只创建Socket对象,未指定IP地址和端口号,只创建了客户端对象,没有连接服务器,要想正常通信,需要调用connect(SocketAddress endpint)方法,才能完成完成与指定服务起的连接,endpint指定IP地址和端口号。
(2) Socket(String host,int port):创建连接指定IP和端口的Socket对象;
(3) Socket(InetAddress address,int port):与上面相似,address封装了IP地址信息。
其他方法:
(1) Int getPost():返回一个int型对象,为Socket连接端口信息;
(2) InetAddress getLocalAddress():获取Socket对象绑定的本地IP地址信息,并将IP地址封装成InetAddress类型对象进行返回;
(3) close():该方法用于关闭Socket连接,结束本次通信,关闭前需要将所有相关输入输出流全部关闭,以免内存泄漏;
(4) getInputStream():返回一个InputStream对象,如果该对象时是由服务端调用则代表是服务端读取客户端发送的数据,否则为客户端读取服务端发送的数据。
getOutputStream: 返回一个OutputStream对象,如果是由服务端的Socket返回,就用于向客户端发送数据,反之则为客户端向服务端发送数据。
3.实现例子
(1)服务器端
public class Example01 { public static void main(String[] args) throws Exception { // 监听指定的端口 int port = 55533; ServerSocket server = new ServerSocket(port); // server将一直等待连接的到来 System.out.println("server将一直等待连接的到来"); Socket socket = server.accept(); // 建立好连接后,从socket中获取输入流,并建立缓冲区进行读取 InputStream inputStream = socket.getInputStream(); byte[] bytes = new byte[1024]; int len; StringBuilder sb = new StringBuilder(); while ((len = inputStream.read(bytes)) != -1) { //注意指定编码格式,发送方和接收方一定要统一,建议使用UTF-8 sb.append(new String(bytes, 0, len,"UTF-8")); } System.out.println("get message from client: " + sb); inputStream.close(); socket.close(); server.close(); } }
(2)客户端
1 public class Example04 { 2 public static void main(String args[]) throws Exception { 3 // 要连接的服务端IP地址和端口 4 String host = "127.0.0.1"; 5 int port = 8080; 6 // 与服务端建立连接 7 Socket socket = new Socket(host, port); 8 // 建立连接后获得输出流 9 OutputStream outputStream = socket.getOutputStream(); 10 String message="你好,yiwangzhibujian"; 11 socket.getOutputStream().write(message.getBytes("UTF-8")); 12 outputStream.close(); 13 socket.close(); 14 } 15 }
结果展示:
注意:如果希望在命令行运行成功,请保证java源码中没有头部package(包)信息!