首先需要知道:java.net有许多网络通信使用的类,像InetAddress,其主要用途是获取IP、主机名等
1,socket通信适用范围比较广泛,Linux、Windows、java都在使用Socket进行网络通信
2,两个java程序可以通过一个双向的网络通信连接实现数据交换,这个双向链路的一端称为一个socket
3,java.net包中定义的两个类Socket和ServerSocket,分别用来实现双向连接的client和Service端
4,建立连接是所需的寻址信息为远程计算机的IP地址和端口号[port number](通过端口号来区分这个IP地址上不同的应用程序)
5,TCP端口和UDP端口是分开的
如何通信?
首先,用ServiceSocket在服务器端开辟一个端口ServiceSocket serviceSocket = new ServiceSocket(6666),这样服务器端就开始监听6666这个端口,任何从客户端访问这个端口的应用程序都会被建立二者的链接,于是,在客户端Socket s = new Socket("127.0.0.1",6666);(这行语句的作用:使用本机的某个端口(这个端口是随机生成的,反正链接已经建立了,不在乎本机的端口了)来访问服务器端6666这个端口,以建立二者的链接。) 但是这个连接能否建立的关键还在Socket s = ss.accept();这条语句,客户端发送建立连接的请求,只有调用了这个方法后才会成功建立连接。
127.0.0.1是所有本机的IP地址。
下面来看看最简单的同步试的客户服务器端的代码;
服务器端:
public class TCPServer{
public static void main(String[] args) throws Exception{
1,ServerSocket ss = new ServerSocket(6666);
while(true){
3,Socket s = ss.accept(); //采用无限循环的方式来接受客户端的请求
5,System.out.println("a client connect!");
5, DataInputStream dis = new DataInputStream(s.getInputStream());//使用输入流来接受从服务器端发送过来的io流
5 System.out.println(dis.readUTF);
5 dis.close();
5 s.close();
}
}
}
注意:accept()是阻塞试的,例如,在客户端有两个程序或用户A、B访问服务器端,A先访问,但是A中有Sleep(30000000)这样的语句,在服务器端调用accept方法之后就会陷入长时间的阻塞,B就无法访问服务器,它一定要等while()中的这个循环执行完成才能继续访问服务器。
如何解决这个问题:采用异步试。
客户端:
public class TCPClient {
public static void main(String[] args){
2,Socket s = new Socket("127.0.0.1",6666);
4,OutputStream os = s.getOutputStream();
4 DataOutputStream dos = new DataOutputStream(os); //在客户端使用输出流来进行和server的通信
4 //sleep(30000000); //如上面所说sleep(300000000),就会出现上面的问题!
4 dos.writeUTF("hello server!");
4 dos.flush();
4 dos.close();
4 s.close();
}
}
一个服务器的端口可以有多个客户端连接,但是不能开启多个相同端口的服务器,像连续编译运行两个Server的代码必回报错!
代码执行顺序如代码中的数字。(要先运行Server,再运行Client)。
当然,server也可以传递数据给client,实现数据的双向传递
server:
client:
由于服务器端是先读后写,所以客户端必须先写后读。否则,由于readUTF方法是阻塞式的,那么他会一直等待客户端的数据,但是客户端也是读,这样就陷入了无限等待之中。