Java 基于UDP/TCP的socket多线程/单线程编程

在Socket编程时,记住要先启动服务器,后启动客户端。

单线程Socket的TCP通信

主要使用的类:

Socket:

  • Socket()      创建一个未连接的套接字,并使用系统默认类型的SocketImpl
  • Socket(InetAddress address,int port)       创建流套接字并将连接到指定的IP地址的指定端口号
  • InetAddress getInetAddress()        返回套接字所连接的地址
  • InputStream getInputStream()       返回此套接字的输入流
  • OutputStream getOutputStream()  返回此套接字的输出流
  • int getPort()             返回此套接字连接到的远程端口号

ServerSocket:

实现了服务器套接字。服务器套接字等待通过网络进入的请求。它根据该请求执行一些操作,然后将结果返回给请求者。

  • ServerSocket()    创建未绑定的服务器套接字
  • ServerSocket(int port)     创建绑定到指定端口的服务器套接字    
  • Socket accept()      监听套连接到此套接字并接收它
  • int   getLocalPort()   返回此套接字正在监听的端口号

1.Server

  1. 创建ServerSocket对象,绑定监听端口
  2. 通过accept()方法监听客户端请求
  3. 连接建立后,通过输入流读取客户端发送的请求信息
  4. 通过输出流向客户端发送响应信息
public class Server {
    
	public static void main(String[] args) {
		//1.创建一个服务器端的ServerSocket,指定绑定的端口
		try {
			ServerSocket serverSocket=new ServerSocket(8888);
			//2.调用accept()开始监听,等待客户端的连接
			System.out.println("***服务器即将启动,等待客户端的连接***");
			Socket socket=serverSocket.accept();
			//3.获取输入流,读取客户端信息
			InputStream is=socket.getInputStream();
			InputStreamReader isr=new InputStreamReader(is);
			BufferedReader br=new BufferedReader(isr);
			String data=null;
			while((data=br.readLine())!=null) {
				System.out.println("服务器:"+data);
			}
			socket.shutdownInput();
			//4.获取输出流,响应客户端的请求
			OutputStream os=socket.getOutputStream();
			PrintWriter pw=new PrintWriter(os);
			pw.write("欢迎您");
			pw.flush();
			//5.关闭各种资源
			pw.close();
			os.close();
			br.close();
			isr.close();
			is.close();
			socket.close();
			serverSocket.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

2.Client

1.创建Socket对象,指明需要连接的服务器的地址和端口号

2.连接建立后,通过输出流向服务器端发送请求信息

3.通过输入流获取服务器响应的信息

4.关闭相关资源

public class Client {

	public static void main(String[] args) {
		try {
			//1.创建客户端Socket,指定服务器地址和端口
			Socket socket=new Socket("localhost",8888);
			//2.获取输出流
			OutputStream os=socket.getOutputStream();
			PrintWriter pw=new PrintWriter(os);
			pw.write("用户名:admin;密码:123");
			pw.flush();
			socket.shutdownOutput();
			
			//3.获取输入流
			InputStream is=socket.getInputStream();
			InputStreamReader isr=new InputStreamReader(is);
			BufferedReader br=new BufferedReader(isr);
			String data=null;
			while((data=br.readLine())!=null) {
				System.out.println("客户端:"+data);
			}
			socket.shutdownInput();
			
		    //4.关闭资源
			br.close();
			isr.close();
			is.close();
			pw.close();
			os.close();
			socket.close();
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}

多线程Socket的TCP通信

客户端保持不变,只需修改服务器端代码。

1.ServerThread

public class ServerThread extends Thread {
	Socket socket=null;
	public ServerThread(Socket socket) {
		this.socket=socket;
	}
	//线程执行的操作,响应客户端的请求
	public void run(){
		InputStream is=null;
		PrintWriter pw=null;
		OutputStream os=null;
		BufferedReader br=null;
		InputStreamReader isr=null;
		
		try {
			is = socket.getInputStream();
			isr=new InputStreamReader(is);
			br=new BufferedReader(isr);
			String data=null;
			while((data=br.readLine())!=null) {
				System.out.println("服务器:"+data);
			}
			socket.shutdownInput();
			//4.获取输出流,响应客户端的请求
			os=socket.getOutputStream();
			pw=new PrintWriter(os);
			pw.write("欢迎您");
			pw.flush();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			try {
				//5.关闭各种资源
				if(pw!=null)
				    pw.close();
				if(os!=null)
				    os.close();
				if(br!=null)
				    br.close();
				if(isr!=null)
				    isr.close();
				if(is!=null)
					is.close();
				if(socket!=null)
				    socket.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

2.Server

public class Server {
    
	public static void main(String[] args) {
		//1.创建一个服务器端的ServerSocket,指定绑定的端口
		try {
			int count=0;   //客户端数量
			ServerSocket serverSocket=new ServerSocket(8888);
			//2.调用accept()开始监听,等待客户端的连接
			System.out.println("***服务器即将启动,等待客户端的连接***");
			Socket socket=null;
			while(true) {
				socket=serverSocket.accept();
				ServerThread serverThread =new ServerThread(socket);
				serverThread.setPriority(4);
				serverThread.start();
				count++;
				System.out.println("客户端数量:"+count);
				InetAddress address=socket.getInetAddress();
				System.out.println("当前客户端是IP地址:"+address.getHostAddress());
			}
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

在使用多线程的时候,一定要注意优先级的设置!!!

对于同一个socket,如果关闭了输出流,则与该输出流关联的socket也会被关闭,所以一般不用关闭流,直接关闭socket即可。

单线程Socket的UDP通信

DatagramSocket:

用于发送和接收数据报数据包的套接字。

  • DatagramSocket()               构造数据报套接字并将其绑定到本地主机上的任何可用端口。
  • DatagramSocket(int port)    构造数据报套接字并将其绑定到本地主机上的指定端口
  • void receive(DatagramPacket p)   从此套接字接收数据报包
  • void send(DatagramPacket p)       从此套接字发送数据报包
  • void setSoTimeout(int timeout)      以指定的超时(以毫秒为单位)启动/禁用SO_TIMEOUT

DatagramPacket:数据报包

  • DatagramPacket(byte[] buf,int length)  构造一个DatagramPacket用于接收length长度的数据包。
  • DatagramPacket(byte[] buf,int length,InetAddress address,int port)  构造用于发送length长度的分组的数据报,指定主机上到指定的端口号。
  • InetAddress getAddress()       返回该数据报发送或接受数据报的计算机的IP地址。
  • byte[]  getData()                      返回数据缓冲区。
  • int getLength()                        返回要发送的数据的长度或接收到的数据的长度。
  • int getPort()                             返回发送数据报的远程主机上的端口号,或从中接收数据报的端口号。

1.Server

  1. 创建DatagramSocket,指定端口号
  2. 创建DatagramPacket
  3. 接收客户端发送的数据信息
  4. 读取信息
public class server {

	public static void main(String[] args) throws IOException {
		//1.创建服务器段DatagramSocket,并指定端口
		DatagramSocket socket=new DatagramSocket(8800);
	    System.out.println("***服务器端已启动,等待客户端连接***");
		//2.创建数据报,用于接收客户端发送的数据
		byte[] data=new byte[1024];
		DatagramPacket packet=new DatagramPacket(data,data.length);
		//3.接收客户端发送的数据
		socket.receive(packet);   //此方法在接收到数据报之前会一直阻塞
		//4.读取数据
		String info=new String(data,0,packet.getLength());
		System.out.println("服务器:"+info);
		
		/*
		 * 向客户端响应数据
		 */
		//1.定义客户端的地址,端口,数据
		InetAddress address=packet.getAddress();
		int port=packet.getPort();
		byte[] data2="欢迎您! ".getBytes();
		//2.创建数据报,包含响应的数据信息
		DatagramPacket packet2=new DatagramPacket(data2,data2.length,address,port);
		//3.相同客户端
		socket.send(packet2);
		//关闭资源
		socket.close();
	}

}

2.Client

  1. 定义发送信息
  2. 创建DatagramPacket,包含将要发送的信息
  3. 创建DatagramPacket
  4. 发送数据
public class client {

	public static void main(String[] args) throws IOException {
		//1.定义服务器的地址,端口号,数据
		InetAddress address=InetAddress.getByName("localhost");
		int port=8800;
		byte[] data="用户名:admin;密码:123".getBytes();
		//2.创建数据报,包含发送的数据信息
		DatagramPacket packet=new DatagramPacket(data,data.length,address,port);
		//3.创建DatagramSocket对象
		DatagramSocket socket=new DatagramSocket();
		//4.向服务器端发送数据报
		socket.send(packet);

		/*
		 * 接收服务端响应的数据
		 */
		byte[] data2=new byte[1024];
		DatagramPacket packet2=new DatagramPacket(data2,data2.length);
		socket.receive(packet2);
		String reply=new String(data2,0,packet2.getLength());
		System.out.println("客户端:"+reply);
		socket.close();
	}

}

多线程Socket的UDP通信

1.ServerThread

public class ServerThread extends Thread {
	DatagramSocket socket=null;
	DatagramPacket packet=null;
	public ServerThread(DatagramSocket socket,DatagramPacket packet) {
		this.socket=socket;
		this.packet=packet;
	}
	public void run() {

		//4.读取数据
		String info=new String(packet.getData(),0,packet.getLength());
		System.out.println("服务器:"+info);
		
		/*
		 * 向客户端响应数据
		 */
		//1.定义客户端的地址,端口,数据
		InetAddress address=packet.getAddress();
		int port=packet.getPort();
		byte[] data2="欢迎您! ".getBytes();
		//2.创建数据报,包含响应的数据信息
		DatagramPacket packet2=new DatagramPacket(data2,data2.length,address,port);
		//3.相同客户端
		try {
			socket.send(packet2);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

2.Server

public class server {

	public static void main(String[] args) throws IOException {
		//1.创建服务器段DatagramSocket,并指定端口
		int count=0;
		DatagramSocket socket=new DatagramSocket(8800);
	    System.out.println("***服务器端已启动,等待客户端连接***");
        while(true) {
    		//2.创建数据报,用于接收客户端发送的数据
    		byte[] data=new byte[1024];
    		DatagramPacket packet=new DatagramPacket(data,data.length);
    		//3.接收客户端发送的数据
    	    socket.receive(packet);  //此方法在接收到数据报之前会一直阻塞
        	ServerThread servletThread=new ServerThread(socket,packet);
        	servletThread.setPriority(4);
        	servletThread.start();
			count++;
			System.out.println("客户端数量:"+count);
        }
	}

}

猜你喜欢

转载自blog.csdn.net/ljcgit/article/details/81450491