Java网络编程

1:网络编程TCP协议

TCP是一个可靠的协议,面向连接的协议。

实现TCP程序,需要编写服务器端和客户端,Java API为我们提供了java.net包,为实现网络应用程序提供类。

ServerSocket :此类实现服务器套接字。

Socket :此类实现客户端套接字(也可以就叫“套接字”)。

通过Socket实现网络编程 Socket是网络驱动层提供给应用程序编程的接口和一种机制。

 2:TCP实现ECHO程序

Echo,意为应答,程序的功能是客户端向服务器发送一个字符串,服务器不做任何处理,直接把字符串返回给客户端,Echo程序是最为基本的客户/服务器程序。

3:服务器与多客户端通信

   服务器端通过加入线程池来处理多个客户端请求,简单的线程数可以与CPU的核数匹配,过多的线程空闲会浪费cpu的资源

服务器端:

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 处理多个客户端
 * 主线程用于监听客户端的连接,每次连接成功,会开启一个线程来处理
 * 这样就会很方便的做到一个服务器处理多个客户端响应的数据了
 *
 */

public class MuyilServerDemo {

	public static void main(String[] args) {
		
		//创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。返回类型是ExecutorService
		ExecutorService es= Executors.newFixedThreadPool(3);

		try {
			ServerSocket server = new ServerSocket(6666);
			System.out.println("服务器已经启动,等待客服端连接...");
			
			while(true){
				Socket s=server.accept();
				System.out.println(s.getInetAddress().getHostAddress());
				es.execute(new UserThread(s));//需要传参Runnable类型
			}
			
		} catch (IOException e) {
			 e.printStackTrace();
		}
		
	}

}

class UserThread implements Runnable{
	private Socket s;
	
	public UserThread(Socket s) {
		super();
		this.s = s;
	}

	@Override
	public void run() {
		try {
			//服务器端先读后写,先写入输入流
			BufferedReader br=new BufferedReader(
					new InputStreamReader(s.getInputStream()));
			
			PrintStream ps=new PrintStream(
					new BufferedOutputStream(s.getOutputStream()));
			
			String info=br.readLine();
			System.out.println(info);
			
			ps.println("echo"+info); 
			ps.flush();
			
			//关闭流
			ps.close();
			br.close();
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
}

客户端:

public class MutilClientDemo {

	/**
	 * 客户端需要多次传向服务端
	 */
	public static void main(String[] args) {
		Scanner input=new Scanner(System.in);
		try {
			Socket socket=new Socket("localhost",6666);
			PrintStream ps=new PrintStream(new BufferedOutputStream(socket.getOutputStream()));
			BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
			
			//客户端需要先写再读
			System.out.println("请输入数据: ");
			String info=input.nextLine();
			ps.println(info);
			ps.flush();
			
			info=br.readLine();
			System.out.println(info);
			
			br.close();
			ps.close();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

4:多客户端之间的通信(难点)

        之前的学习是可以实现客户端与服务器之间的通信,那么如何实现多个客户端之间的通信呢?

实现多个客户端之间的通信,使用服务器作为中间站,把消息进行集中处理

Message.java:

import java.io.Serializable;

/**
 * 1:需要将发消息的信息进行封装
 * String from	发送者
 * Stirng to	接受者
 * int type	发送消息的类型
 * String info	信息内容 
 */

@SuppressWarnings("serial")
public class Message implements Serializable{
	private String from;
	private String to;
	private int type;
	private String info;
	public Message(String from, String to, int type, String info) {
		super();
		this.from = from;
		this.to = to;
		this.type = type;
		this.info = info;
	}
	public Message() {
		super();
	}
	public String getFrom() {
		return from;
	}
	public void setFrom(String from) {
		this.from = from;
	}
	public String getTo() {
		return to;
	}
	public void setTo(String to) {
		this.to = to;
	}
	public int getType() {
		return type;
	}
	public void setType(int type) {
		this.type = type;
	}
	public String getInfo() {
		return info;
	}
	public void setInfo(String info) {
		this.info = info;
	}
	@Override
	public String toString() {
		return "Message [from=" + from + ", info=" + info + ", to=" + to
				+ ", type=" + type + "]";
	}
	
	
}

 MessageType.java

/**
 * 定义消息的类型
 * 可以是登陆.发送
 * 后续还可以是注册等等
 */
public class MessageType {
		public static final	int TYPE_SEND=1;
		public static final	int TYPE_LOGIN=2;
}

 Client.java

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;


public class Client {


	/**
	 * 多客户端之间连接
	 */
	public static void main(String[] args) {
		//1:与服务器建立好连接
		
		//2:启动读取(接受Message)消息的线程
		
		//3:使用主线程来实现发送信息
			
		Scanner input=new  Scanner(System.in);

		//加入线程池
		Executor ex=Executors.newSingleThreadExecutor();
		
		ObjectOutputStream oos=null;
		ObjectInputStream ois=null;
		try {
			Socket socket=new Socket("localhost",7777);
			System.out.println("服务器连接成功");
			oos=new ObjectOutputStream(socket.getOutputStream());
			ois=new ObjectInputStream(socket.getInputStream());
			//向服务器发送登陆信息
			System.out.println("请输入名称:");
			//登陆用户客户端名称
			String name=input.nextLine();
			Message msg=new Message(name, null, MessageType.TYPE_LOGIN, null);
			oos.writeObject(msg);
			msg=(Message)ois.readObject();
			System.out.println(msg.getInfo()+msg.getFrom());//其中的Info就是服务器端我的欢迎你,.getForm就是写入的名称
			
			//启动读取消息的线程
			ReaderInfoThread rit=new ReaderInfoThread(ois);
			ex.execute(rit);
			boolean flag=true;
			while(flag){
				msg=new Message();
				System.out.println("发给;");
				msg.setTo(input.nextLine());
				msg.setFrom(name);
				msg.setType(MessageType.TYPE_SEND);
				System.out.println("发送的内容:");
				msg.setInfo(input.nextLine());
				oos.writeObject(msg);
			}
			
			
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}finally{
			try {
				ois.close();
				oos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		
		}
	}

}

//读取消息的线程
class ReaderInfoThread implements Runnable{
	private ObjectInputStream ois;
	private boolean flag=true;
	
	public ReaderInfoThread(ObjectInputStream ois) {
		this.ois = ois;
	}
	
	public void setFlag(boolean flag){
		this.flag=flag;
	}
	
	@Override
	public void run() {
			try {
				while(flag){
				Message msg=(Message)ois.readObject();
				System.out.println("["+msg.getFrom()+"]"+"对你说:"+msg.getInfo());
				}
				//如果不关闭  ,就会一直读
				if(ois!=null){
					ois.close();
				}
				ois.close();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		
		
	}
	
}

Server.java

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Server{

	/**
	 * 多客户端之间进行通信
	 */
	
	public static void main(String[] args) {
		//1:保存客户端处理的线程(使用Vector去保存)
		
		//2:创建服务器端的Socket,socket在接受到后需要到线程中去处理
		
		//3:在方法快中使用定义的类去将vector传参,在UserThread类中去操作数据处理
		
			Vector<UserThread> v=new Vector<UserThread>();
			//创建线程池
			ExecutorService es=Executors.newFixedThreadPool(5);
			try {
				ServerSocket ss=new ServerSocket(7777);
				System.out.println("服务器已经启动,等待客户端连接,,,");
				while(true){
					Socket socket=ss.accept();
					UserThread nt=new UserThread(socket,v);
					es.execute(nt);
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			
	}

}

class UserThread implements Runnable{
	private String name;//客户端的名称,在登陆后
	private Socket socket;
	private	ObjectInputStream ois;
	private ObjectOutputStream oos;
	private boolean flag=true;
	
	//写入集合是为了线程之间可以进行认识,以确定客户端的信息课通过线程传输得到其他的客户端
	private Vector<UserThread> v;
	
	public UserThread(Socket socket, Vector<UserThread> v) {
		this.v=v;
		this.socket = socket;
		//需要将创建的对象添加到集合中去
		v.add(this);
	}	

	@Override
	public void run() {
		System.out.println("客户端"+socket.getInetAddress().getHostAddress()+"已连接");
		try {
			ois=new ObjectInputStream(socket.getInputStream());
			oos=new ObjectOutputStream(socket.getOutputStream());
			while(flag){
				//读取消息
				Message msg=(Message)ois.readObject();
				int type=msg.getType();//或许需要操作的类型
				switch(type){
					case MessageType.TYPE_LOGIN://登陆
						name=msg.getFrom();
						msg.setInfo("欢迎你: ");//写入内容之中
						oos.writeObject(msg);//发送给客户端
					break;
					
					case MessageType.TYPE_SEND://发送信息
						String to=msg.getTo();//指定需要发现谁
						//需要将to和服务器之中的线程池做比较,如果相等,则发送信息
						UserThread ut ;
						for (int i = 0; i <v.size(); i++) {
							ut=v.get(i);
							if(to.equals(ut.name)&&ut!=this ){
								ut.oos.writeObject(msg);
								break;
							}
						}
					break;
				}
			}
			ois.close();
			oos.close();
			
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

	
}

 

5:网络编程UDP协议

UDP协议是一种无连接的协议

主要使用以下的两个类:

DatagramPacket:此类表示数据报包。

DatagramSocket:此类表示用来发送和接收数据报包的套接字

public class Send {

	/**
	 * 实现无链接发生信息.类似QQ聊天,文件传输等
	 * 
	 * 发送方实现步骤:
	 * 		1:获取本地地址
	 * `	2:创建DatagramPacket对象来存储数据
	 * 		3:创建DatagramSocket对象发送DatagramPacket中存储的数据
	 */
	public static void main(String[] args) {
		DatagramSocket ds=null;
		String mess="咨询问题";
		try {
			//创建DatagramSocket对象,并连接套接字
			ds=new DatagramSocket();
			
			//获取本机地址
			InetAddress ia=InetAddress.getByName("localhost");
			
			//实现无连接传输数据,封装数据
			DatagramPacket dp=new DatagramPacket(mess.getBytes(),mess.getBytes().length,ia,8888);
			ds.send(dp);
			
		} catch (SocketException e) {
			e.printStackTrace();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			ds.close();
		}	
		
	}

}


import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class Receive {

	/**
	 *	实现无链接发生信息.类似QQ聊天,文件传输等
	 *
	 *	接收方实现步骤:
	 *		1:创建DatagramSocket对象,实现套接字作为连接
	 *		2:创建DatagramPacket对象,实现需要传输的数据保存
	 *		3:使用DatagramSocket创建的对象来接受和传输DatagramPacket中存储的数据到知道ip和端口去
	 */
	public static void main(String[] args) {
		
		//DatagramSocket表示发送和接受包的套接字
		DatagramSocket ds=null;
		
		//创建DatagramPacket来实现无连接包传输
		byte[] by=new byte[1024];
		DatagramPacket dp=new DatagramPacket(by, 1024);
		
		try {
			//创建DatagramSocket来接受数据
			ds=new DatagramSocket(8888);
			//接受由DatagramPacket创建的对象传输的包
			ds.receive(dp);
			
			//输出传输的数据
			String mess=new String(dp.getData(), 0, dp.getLength());
			System.out.println(ds.getInetAddress().getHostAddress()+"说:"+mess);
		} catch (SocketException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			ds.close();
		}
	}

}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java网络编程是一种通过使用Java编程语言,在计算机网络上实现通信的技术。它涉及到协议、IP地址和端口号等三个重要要素。Java编写的应用程序可以在单个计算机上运行,也可以在网络的服务器端和客户端上分布运行。此外,Java还可以用于编写小型应用程序模块或applet,作为网页的一部分使用。applet可以嵌入网页中,并在浏览器中运行。在Java中,使用URI可以代表绝对的或相对的资源,而URL则包含了定位资源的信息,并且不能是相对的。Java提供了一系列的类和接口,例如InetAddress、Socket、ServerSocket、URL和URLConnection等,用于实现各种网络应用。通过使用这些类和接口,可以创建连接客户端和服务器之间的套接字,并实现面向连接的通信,保证数据的可靠传输。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Java网络编程](https://blog.csdn.net/weixin_42784609/article/details/130388655)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [超详细入门到精通自学视频课程(阶段01:JavaSE基础02 编程思维编程思维和编程能力、综合应用专题-04、案例...](https://download.csdn.net/download/weixin_54787054/88224199)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [网络编程](https://blog.csdn.net/zhixingwu/article/details/103226003)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值