Java网络编程(二)

网络编程2

一、什么是TCP,它的优缺点是什么?

TCP--传输控制协议[有连接的协议]

优点:保证数据安全可靠

缺点:消耗大,效率低

二、建立基于TCP的网络通讯程序需要使用的类和常用方法?

   基于TCP的网络通讯程序是区分客户端和服务器端

   创建客户端程序

        1.java.net Class Socket 创建基于TCP的通讯程序的客户端对象的java类

           通过这个类创建的对象就表示一个客户端

        2.构造方法

Socket(InetAddress address, int port)

创建流套接字并将其连接到指定IP地址的指定端口号。

Socket(String host, int port)

创建流套接字并将其连接到指定主机上的指定端口号。

        3.常用实例方法

OutputStream

getOutputStream() 返回此套接字的输出流。

InputStream

getInputStream() 返回此套接字的输入流。

void

close() 关闭此套接字。

  创建服务器端程序

        1.java.net Class ServerSocket 创建基于TCP的通讯程序的服务器端对象的java类

           通过这个类创建的对象就表示一个服务器端

        2.构造方法

ServerSocket(int port)

创建绑定到指定端口的服务器套接字。

        3.实例方法

Socket

accept() 侦听要连接到此套接字并接受它。 【阻塞主线程运行】

void

close() 关闭此套接字。

例如:

完成客户端向服务器送数据,服务器接收到客户端发送来的数据。

客户端向服务器送数据

package com.wangxing.test1;

import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

/**
 * 基于TCP的客户端【发送数据】
 * 
 * @author 14336
 *
 */
public class TestClient1 {
	public static void main(String[] args) throws Exception {
		//定义服务器端的ip
		  InetAddress serverIP=InetAddress.getLocalHost();
		//定义服务器端的port(接口)
		  int serverport=3000;//(0~1024被系统使用)
		//创建客户端对象
		  Socket client=new Socket(serverIP,serverport);//客户端链接哪个服务器。
		//定义Scanner对象获取控制台输入的信息
		  Scanner input=new Scanner(System.in);
		  System.out.println("请输入要发送的数据:");
		  String info=input.nextLine();
		 //得到输出流
		  OutputStream outputStream=client.getOutputStream();
		 //写出数据
		  outputStream.write(info.getBytes());
		 //关闭流
		  outputStream.close();
		  //关闭客户端Socket
		  client.close();
	}
}

服务器接收到客户端发送来的数据

package com.wangxing.test1;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 基于TCP的服务器【接受数据】
 * @author 14336
 *
 */
public class TestServer {
	public static void main(String[] args) throws Exception {
		//指定服务器开启的端口
		int serverport=3000;
		//创建服务器对象
		ServerSocket serverSocket=new ServerSocket(serverport);
		System.out.println("服务器准备完毕,等待客户端连接。。。");
		//等待客户端连接
		//在客户端没有进行连接之前此方法一直阻塞
		//serverSocket.accept();此方法是ServerSocket中的方法返回值是Socket类型
		Socket client1=serverSocket.accept();
		//通过连接进来的客户端对象得到输入流,以接收客户端发送来的数据
		InputStream inputStream=client1.getInputStream();
		//创建保存发送来数据用的字节数组
		byte[] b=new byte[1024];
		//读取客户端发送来的数据保存到数组b中
		int len=inputStream.read(b);
		//将保存在字节数组中的数据转换成String
		String msg=new String(b);
		System.out.println("接受的数据是:"+msg);
		//关闭流
		inputStream.close();
		//关闭Socket
		client1.close();
		//关闭服务器
		serverSocket.close();
		
		
		
	}
}

例如2:

完成客户端持续向服务器送数据,服务器持续接收到客户端发送来的数据。

客户端持续向服务器送数据

package com.wangxing.test2;

import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

/**
 * 基于TCP的客户端【持续发送数据】
 * @author 14336
 *
 */
public class TestClient2 {

		public static void main(String[] args) throws Exception {
			//服务器IP
			InetAddress serverIP=InetAddress.getLocalHost();
			//服务器端口
			int serverport=3000;
			//客户对象
			Socket client=new Socket(serverIP,serverport);
			//Scanner 
			Scanner input=new Scanner(System.in);
			//控制循环的变量
			boolean flag=true;
			//得到输出流
			OutputStream outputStream=client.getOutputStream();
			//控制持续发送
			while(flag){
				System.out.println("请输入需要发送的数据:");
				String info=input.nextLine();
				//写出数据
				outputStream.write(info.getBytes());
				//根据输入的数据判断是否关闭客户端
				if (info.equals("886")) {
					flag=false;
				}
			}
			//关闭流
			outputStream.close();
			//关闭Socket
			client.close();
		}
}

服务器持续接收到客户端发送来的数据

package com.wangxing.test2;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 基于TCP的服务器【接受数据】
 * @author 14336
 *
 */
public class TestServer2 {
		public static void main(String[] args) throws Exception {
			//指定服务器开启端口
			int serverport=3000;
			//创建服务器对象
			ServerSocket server1=new ServerSocket(serverport);
			System.out.println("服务器准备完毕,等待客户端连接:");
			//等待客户端连接
			Socket client1=server1.accept();
			//通过连接进入的客户端对象得到输入流,以接收客户端发送来的数据
			InputStream inputStream=client1.getInputStream();
			//定义持续接受的控制变量
			boolean flag=true;
			//创建保存发送来的数据用的字节数组
			byte data[]=new byte[1024];
			while (flag) {
				//读取客户端发送来的数据
				int len=inputStream.read(data);
				//将保存在字节数组中的数据转换成String
				//String(data,0,len)注意这一步,读多少转换多少
				// String(data)==String(data,0,data.length),
				//a     a
				//abc   abc
				//d     dbc
				
				String msg =new String(data,0,len);
				System.out.println("接受到的数据是:"+msg);
				if (msg.equals("886")) {
					flag=false;
				}
			}
			//关闭流
			inputStream.close();
			//关闭Socket
			client1.close();
			//关闭服务器
			server1.close();
			
		}
}

例如2:

完成客户端持续向服务器送数据,还能接收服务器返回的信息,服务器持续接收到客户端发送来的数据,还可以向客户端返回信息。

客户端持续向服务器送数据,还能接收服务器返回的信息

package com.wangxing.test3;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

/**
 * 基于TCP的客户端【持续发送数据】
 * @author 14336
 *
 */
public class TestClient3 {
		public static void main(String[] args) throws Exception {
			//定义服务器IP
			 InetAddress serverIP=InetAddress.getLocalHost();
			//定义服务器端的port
			 int serverport=3000;
			 //创建客户端对象
			 Socket client=new Socket(serverIP, serverport);
			 //定义Scanner(扫描)对象
			 Scanner input=new Scanner(System.in);
			 //定义控制持续发送的变量
			 boolean flag=true;
			 //得到输出流
			 OutputStream outputStream=client.getOutputStream();
			 //得到输入流
			 InputStream inputStream=client.getInputStream();
			 //定义保存读取数据的字节数组
			 byte data[]=new byte[1024];
			 //控制持续发送
			 while(flag){
				 System.out.println("请输入要发送的数据:");
				 String info=input.nextLine();
				 //写出数据
				 outputStream.write(info.getBytes());
				//根据输入的数据判断是否关闭客户端
				 if (info.equals("886")) {
					System.out.println("客户端关闭!");
					flag=false;
				 }else{
					 //开始接收服务器返回的数据
					int len=inputStream.read(data); 
					//将读取到的数据保存在字节数组中
					//将保存在字节数组中的数据转换成String
					String msg=new String(data,0,len);
					System.out.println("接受来自服务器的数据是:"+msg);
				 }
			 }
			 //最后用哪个,就先关谁
			 //关闭流
			 inputStream.close();
			 outputStream.close();
			 //关闭Socket
			 client.close();
		}
}

服务器持续接收到客户端发送来的数据,还可以向客户端返回信息

package com.wangxing.test3;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.time.format.FormatStyle;

/**
 * 基于TCP的服务器【接受数据】
 * @author 14336
 *
 */
public class TestServer3 {
		public static void main(String[] args) throws Exception {
			//指定服务器开启的端口
			int serverport=3000;
			//创建服务器对象
		    ServerSocket server1=new ServerSocket(serverport);
			System.out.println("服务器准备完毕,等待客户连接....");
			//等待客户连接
			Socket client1=server1.accept();
			//通过连接进来的客户端对象得到输入流,以接受客户端发来的数据
			InputStream inputStream=client1.getInputStream();
			//定义持续接受的控制变量
			boolean flag=true;
			//创建保存发送来的数据用的字节数组
			byte[] data=new byte[1024];
			//得到输出流
			OutputStream outputStream=client1.getOutputStream();
			
			while (flag) {
				//读取客户端发送来的数据
				int len=inputStream.read(data);
				//将保存在字节数组中的数据转换成String
				String msg=new String(data,0,len);
				System.out.println("接受的数据是:"+msg);
				//由接受到的数据控制服务器关闭
				if (msg.equals("886")) {
					flag=false;
				}else {
					//开始发送数据
					msg="server"+":"+msg;
					outputStream.write(msg.getBytes());
				}
			}
			//关闭流
			outputStream.close();
			inputStream.close();
			//关闭Socket
			client1.close();
			//关闭服务器
			server1.close();
		}
}

例如:

多客户端,配置一台服务器,独立运行

//客户端

package com.wangxing.test4;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

/**
 * 基于TCP的客户端【持续发送数据】
 * @author 14336
 *
 */
public class TestClient3 {
		public static void main(String[] args) throws Exception {
			//定义服务器端的IP
		    InetAddress serverIP=InetAddress.getLocalHost();
		    //定义服务器端的port端口
		    int serverport=3000;
		    //创建客户端对象
		    Socket client=new Socket(serverIP, serverport);
		    //定义Scanner 
		    Scanner input=new Scanner(System.in);
		    //定义控制持续发送的变量
		    boolean flag=true;
		    //得到输出流
		    OutputStream outputStream=client.getOutputStream();
		    //得到输入流
		    InputStream inputStream=client.getInputStream();
		    //定义保存读取数据的字节数组
		    byte[] data=new byte[1024];
		    //控制持续发送
		    //while (!(input.equals("886"))) 中判断条件只能判断一次
		   
		    while (flag) {
				System.out.println("请输入需要发送的数据:");
				String info=input.nextLine();
				//写出数据
				outputStream.write(info.getBytes());
				if (info.equals("886")) {
					//System.out.println("客户端关闭");
					flag=false;
				}else{
				//开始接收服务器返回的数据
				int len=inputStream.read(data);
				//将保存在字节数组中的数据转换成String
				String msg=new String(data,0,len);
				System.out.println("接收来自服务器的数据是:"+msg);
				}
		    }
		   
		   
		    //客户端关闭
		    System.out.println("客户端关闭!");
	 //关闭流
		    outputStream.close();
		    inputStream.close();
		    //关闭Socket
		    client.close();
		}
}

//服务器为连接到服务器的每一个客户端构造的线程类

package com.wangxing.test4;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

/**
 * 客户端线程类
 * @author 14336
 *
 */
public class ClientThread implements Runnable {
	private Socket client;
	private InputStream in;
	private OutputStream out;
	private boolean flag=true;
	public ClientThread(Socket client) {
		this.client=client;
	}
	public  static int  CiShu(){
		int i=0;
		i++;
		return i;
	}
	
	//完成在服务器中的数据读写操作
	@Override
	public void run() {
		
		//创建读写数据用户输入输出流对象,就需要客户端对象
		 try {
			 in=client.getInputStream();
			 out=client.getOutputStream();
			 //定义保存数据的字节数组
			 byte[] data=new byte[1024];
			 Thread thread=new Thread();
			 thread.setName("客户"+CiShu());
			 while(flag){
				 //读取数据到字节数组
				 int len= in.read(data);
				 //将读取来保存在字节数组中的数据转换成String
				 String msg=new String(data,0,len);
				 System.out.println("读取来自"+thread.getName()+"的数据是:"+msg);
				 //判断退出
				 if (msg.equals("886")) {
					System.out.println("客户端从服务器退出");
					//关闭这条线程
					flag=false;
				}else {
					msg="server :"+msg;
					out.write(msg.getBytes());
				}
			}
			 //关闭流
			 out.close();
			 in.close();
			 //关闭Socket
			 client.close();
			 
		} catch (Exception e) {
			e.printStackTrace();
		}
		  
	}
}

//服务器主程序

package com.wangxing.test4;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 基于TCP的服务器【接收数据】
 * @author 14336
 *
 */
public class TestServer3 {

	public static void main(String[] args) throws Exception {
		//指定服务器开启的端口
		int serverport=3000;
		//创建服务器对象
		ServerSocket server1=new ServerSocket(serverport);
		System.out.println("服务器准备完毕,等待客户端连接....");
		
		//定义控制接收客户端的变量
		boolean flag=true;
		while(flag){
			//等待客户端连接
			Socket client1=server1.accept();
			//一旦有客户链接进入服务器成功
			//我们就需要为每一个成功进入服务器的客户开启独立的线程
			   ClientThread ctThread=new ClientThread(client1);
			   Thread clientThread1=new Thread(ctThread);
	      //开启线程
			 clientThread1.start();
		 }
		//关闭服务器
		server1.close();
		
		
		
		
		
	}
}

总结:

客户端程序的开发步骤:

  1. 创建客户端对象【Socket】,连接服务器
  2. 通过客户端对象【Socket】的getInputStream() / getOutputStream(),得到输入输出流
  3. 通过得到的输入输出流对象调用read()/write()方法完成数据收发。
  4. 关闭输入输出流和客户端对象【Socket】。

服务器程序的开发步骤:

  1. 创建服务器端对象【ServerSocket】,开启服务器
  2. 通过服务器端对象【ServerSocket】的accept()方法,获得连接进入服务器的客户端对象【Socket】
  3. 连接进入服务器的客户端对象【Socket】的getInputStream() / getOutputStream(),得到输入输出流.
  4. 通过得到的输入输出流对象调用read()/write()方法完成数据收发。
  5. 关闭输入输出流和客户端对象【Socket】以及服务器端对象【ServerSocket】。

猜你喜欢

转载自blog.csdn.net/weixin_52192654/article/details/112572338