第十二章 Java网络编程
12.1 网络编程
java是以JVM进程划分网络的(可能一台或多台电脑上会同时运行多个JVM,那么这些不同的JVM彼此都是一台主机),不同的JVM进程表示不同的主机。
网络编程的实质意义在于数据的交互,而在交互过程中一定就会分为服务器端和客户端,而这两端的开发就会存在以下两种模式。
- 形式一:C/S结构,此类模式的开发一般要编写两套程序,一套是客户端代码,另一套属于服务端代码。由于需要有编写程序,所有对于开发以及维护的成本较高。但是由于其使用的是自己的连接端口与交换协议,所有安全性比较高。而C/S结构程序的开发分为两种:TCP(传输控制协议,可靠的传输)、UDP(数据报协议)。
- 形式二:B/S结构,不再单独开发客户端代码,只开发一套服务器端程序,客户端将利用浏览器进行访问,这种模式只需要开发一套程序,但是安全性不高,因为使用的是公共的HTTP协议以及公共的80端口。
12.2 开发第一个网络程序
- ServerSocket类:是一个封装支持TCP协议的操作类,主要工作在服务器端,用于接收客户端请求;
- Socket类:也是一个封装了TCP协议的操作类,每一个Socket对象都表示一个客户端。
ServerSocket类
- public ServerSocket(int port)throws IOException:开辟一个指定的端口监听,一般使用5000以上的端口。
- public Socket accept() throws IOException:服务器端接收客户端请求,通过Socket返回。
- public void close() throws IOException:关闭服务器端。
Socket类
- public Socket(String host,int port)throws UnknownHostException,IOException:指定要连接的主机和端口。
- public OutputStream getOutputStream() throws IOException:取得指定客户端的输出对象,使用PrintStream操作。
- public Input Stream getInputStream() throws IOException:从指定的客户端读取数据,使用Scanner操作。
定义服务器端
public class HelloServer {
public static void main(String[] args)throws Exception{
ServerSocket server=new ServerSocket(9999);
System.out.println("等待客户端连接。。。");
Socket client=server.accept();
//OutputStream并不方便进行内容的输出,所以利用打印流完成输出。
PrintStream out=new PrintStream(client.getOutputStream());
out.println("Hello World!");
out.close();
client.close();
server.close();
}
}
编写客户端
public class TestDemo {
public static void main(String[] args) throws Exception {
Socket client=new Socket("localhost",9999);
Scanner scan=new Scanner(client.getInputStream());
scan.useDelimiter("\n");
if (scan.hasNext()){
System.out.println("[回应数据]"+scan.next());
}
scan.close();
client.close();
}
}
12.3 网络开发的经典模型——Echo程序
实现服务器
public class HelloServer {
public static void main(String[] args)throws Exception{
ServerSocket server=new ServerSocket(9999);
System.out.println("等待客户端连接。。。");
Socket client=server.accept();
//OutputStream并不方便进行内容的输出,所以利用打印流完成输出。
PrintStream out=new PrintStream(client.getOutputStream());
Scanner scan=new Scanner(client.getInputStream());
boolean flag=true;
while (flag){
if (scan.hasNext()){
String str=scan.next().trim();
if (str.equalsIgnoreCase("byebye")){
out.println("拜拜,下次再会");
flag=false;
}else {
out.println("ECHO:"+str);
}
}
}
scan.close();
out.close();
client.close();
server.close();
}
}
修改服务端
public class EchoThread implements Runnable{
private Socket client;
public EchoThread(Socket client){
this.client=client;
}
@Override
public void run(){
try {
Scanner scan=new Scanner(client.getInputStream());
PrintStream out=new PrintStream(client.getOutputStream());
boolean flag=true;
while (flag){
if (scan.hasNext()){
String str=scan.next().trim();
if (str.equalsIgnoreCase("byebye")){
out.println("拜拜,下次再回!");
flag=false;
}else {
out.println("ECHO:"+str);
}
}
}
scan.close();
out.close();
client.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class TestDemo {
public static void main(String[] args) throws Exception {
ServerSocket server=new ServerSocket(9999);
boolean flag=true;
while (flag){
Socket client=server.accept();
new Thread(new EchoThread(client)).start();
}
server.close();
}
}
定义客户端
public class EchoClient {
public static void main(String[] args)throws Exception{
Socket client=new Socket("localhost",9999);
Scanner input=new Scanner(System.in);
Scanner scan=new Scanner(client.getInputStream());
PrintStream out=new PrintStream(client.getOutputStream());
input.useDelimiter("\n");
scan.useDelimiter("\n");
boolean flag=true;
while (flag){
System.out.print("请输入要发送的数据:");
if (input.hasNext()){
String str=input.next().trim();
out.println(str);
if (str.equalsIgnoreCase("byebye")){
flag=false;
}
if (scan.hasNext()){
System.out.println(scan.next());
}
}
}
input.close();
scan.close();
out.close();
client.close();
}
}
未待完。。。。。。。