网络编程


要学好网络编程首先要了解网络通讯相关的知识

1.网络通信的要素

[1],找到对方IP地址

[2],指明要发送数据的端口

[3],遵守通信规则, TCP/IP协议

 

2.理解关键术语

[1] IP地址:网络中设备的标识,由于ip地址不易记忆,可用主机名代替如:www.buaidu.com。本机的ip地址为主机名为:localhost

本地回环地址:127.0.0.1

[2] 端口号:用于标识进程的额逻辑地址,不同进程的标识.有效端口:0~~65535,其中0~1024一般为系统使用或保留端口,只有知道端口号,我们才知道自己要将信息传输给主机上的哪个程序。

[3] 传输协议

(1) UDP---面向无连接

特点:

<1>.将数据及源和目的封装在数据包中,不需要建立连接

<2>.每个数据包的大小限制在64K内

<3>.因为无连接,所以UDP是不可靠协议

<4>应为不需要建立连接,所以速度快 

(2) TCP----面向连接

特点:

<1>.建立连接,形成传输数据的通道

<2>.可以进行大量数据传输

<3>.通过三次握手完成连接,是可靠协议

<4>.由于必须建立连接,所以效率会稍低


通过java编程更深入学习网络编程

提到Java的网络编程不得不了解Socket,网络编程就是Socket编程

Socket(套接字)

1,Socket就是为网络服务提供的一种机制

2,通信两端都有必须有Socket

3,数据在两个Socket间通过IO传输

UDP

项目小实践:通过udp传输方式,将一段文字数据发送出去。,

写一个udp发送端。

思路:

1,建立updsocket服务。

2,提供数据,并将数据封装到数据包中。

3,通过socket服务的发送功能(getOutputStream),将数据包发出去。

4,关闭资源。

eg:

class UdpSend{
	public static void main(String[] args)throws Exception{
		//1
		DatagramSocket ds = new DatagramSocket(8808);
		//2
		byte[] data = "My Name KCH".getBytes();
		DatagramPacket dp = new DatagramPacket(data,data.length,InetAddress.getByName("localhost"),8086);
		//3
		ds.send(dp);
		//4
		ds.close();
	}
}

这样 My Name KCH就发送到所以和本机连接的主机上去了

项目小实践2:接收udp协议传输的数据并处理。

写一个udp的接收端。

思路:

1,定义udpsocket服务

2,定义一个数据包,要存储接受到的字节数据,数据包中有更多功能提取字节数据中的不同数据信息

3,通过socket服务的receive方法将接受到的数据存入数据包中。

4,通过数据包中的方法获取不同数据。

5,关闭资源

eg:

class UdpRece{
	public static void main(String[] args)throws Exception{
		//1
		DatagramSocket ds = new DatagramSocket(8086);
		//2
		byte[] data = new byte[1024];
		DatagramPacket dp = new DatagramPacket(data,data.length);
		//3
		ds.receive(dp);//阻塞式方法,有数据就执行,没数据就等
		//4
		String ip = dp.getAddress().getHostAddress();
		String datas = new String(dp.getData(),0,dp.getLength());
		int port = dp.getPort();
		System.out.println(ip+"--"+port+"--"+datas);
		//5
		ds.close();		
	}
}

掌握了以上udp网络编程的技术后我们就可以写一个自己山寨版的qq了。

思路:

由于聊天是双向的并且一个程序能发送数据也能接受数据,所以我们要在一个程序中写一个发送端一个接受端,并让他们同是工作,那么就要用到多线程技术了,运行是两个动作分别为两个线程,并同时工作,所以要用两个类分别封装发送端和接受端。两个类都要实现Runnable接口

eg:项目小实践3:MyQQ

class Send implements Runnable{
	private DatagramSocket ds;
	Send(DatagramSocket ds){
		this.ds = ds;
	}
	public void run(){
		try{
			BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
			String line = null;
			while((line = bufr.readLine())!= null){
				if("886".equals(line))
					break;
				byte[] buf = line.getBytes();
				DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.137.255"),10000);
				ds.send(dp);
			}
			ds.close();
		}catch(Exception e){
			System.out.println("send exception");
		}
	}
}
class Rece implements Runnable{
	private DatagramSocket ds;
	Rece(DatagramSocket ds){
		this.ds = ds;
	}
	public void run(){
		try{
			byte[] buf = new byte[1024];
			while(true){
				DatagramPacket dp = new DatagramPacket(buf,buf.length);
				ds.receive(dp);

				String ip = dp.getAddress().getHostAddress();
				String datas = new String(dp.getData(),0,dp.getLength());
				int port = dp.getPort();

				System.out.println(ip+"  "+port+"  "+datas);
			}
		}catch(Exception e){
			System.out.println("rece exception");
		}
	}
}
class Chat{
	public static void main(String[] args) throws Exception{
		DatagramSocket ds_send = new DatagramSocket(8064);
		DatagramSocket ds_rece = new DatagramSocket(10000);

		new Thread(new Send(ds_send)).start();
		new Thread(new Rece(ds_rece)).start();
	}
}

TCP

tcp分为客户端和服务端。

客户端对应的对象是Socket

服务端对应的对象是ServerSocket

TCP----->客户端

通过查阅socket对象,发现在该对象建立时,就可以去连接指定主机。如:new Socket(“www.baidu.com“,8086)就是连接了百度服务器的8086端口。

因为tcp是面向连接的。所以在建立socket服务时,就要有服务端存在,并连接成功。形成通路后,在该通道进行数据的传输。

穿件客户端的步骤:

1,建立socket服务。指定要连接主机和端口。

2,获取socket流中的输出流。将数据写到该流中。通过网络发送给服务端。

3,获取socket流中的输入流,将服务端反馈的数据获取到。

4,关闭客户端资源

eg:

class Client{
	public static void main(String[] args)throws Exception{
		//创建一个连接到192.168.137.1主机的8084端口上的socket连接
		Socket s = new Socket("100.64.182.196",8086);
		//定义读取键盘输入的流对象
		BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
		
		//定义一个目的,将数据写入soket输出流发给服务端
		PrintWriter priw_socket = new PrintWriter(s.getOutputStream(),true);

		//定义一个socket读取流,读取服务端返回的数据
		BufferedReader bufr_socket = new BufferedReader(new InputStreamReader(s.getInputStream()));

		String line = null;
		while((line = bufr.readLine())!= null){
			if("over".equals(line))
				break;
			priw_socket.println(line);

			System.out.println("server:"+bufr_socket.readLine());
		}
		s.close();
		bufr.close();
	}
}

TCP--->服务端

建立服务端的步骤:

1,建立服务端的socket服务。ServerSocket(); ,并监听一个端口。 

2,获取连接过来的客户端对象。 通过ServerSokcet的 accept方法。没有连接就会等,所以这个方法是阻塞式的。

3,客户端如果发过来数据,那么服务端要使用对应的客户端对象,并获取到该客户端对象的读取流来读取发过来的数据。

4,关闭服务端(可选)

eg:

class Server{
	public static void main(String[] args)throws Exception{
		ServerSocket ss = new ServerSocket(8086);
		Socket s = ss.accept();

		//定义一个目的,将socket大写数据写入到socket输出流并发送个客户端
		PrintWriter priw_socket = new PrintWriter(s.getOutputStream(),true);
			
		//读取socket流中读取的数据
		BufferedReader bufr_socket = new BufferedReader(new InputStreamReader(s.getInputStream()));
		
		String line = null;
		while((line = bufr_socket.readLine())!= null){
			System.out.println(line);
			priw_socket.println(line.toUpperCase());
		}
		s.close();
		ss.close();
	}
}

掌握了以上tcp的技术我们就可以完成一系列小项目了

eg:项目实践4:多客户端并发上传文件,这就用到了多线程

class Client{
	public static void main(String[] args)throws Exception{
		if(args.length != 1){
			System.out.println("no file");
			return;
		}
		File file = new File(args[0]);
		if(!(file.exists() && file.isFile())){
			System.out.println("file erro of notexist");
			return;
		}
		if(file.length()>1024*1024*4){
			System.out.println("file is too big");
			return;
		}

		Socket s = new Socket("100.64.182.196",8086);

		FileInputStream fis = new FileInputStream(file);

		OutputStream os = s.getOutputStream();

		byte[] buf = new byte[1024];
		int len = 0;
		while((len = fis.read(buf))!= -1){
			os.write(buf,0,len);
		}
		s.shutdownOutput();

		InputStream is = s.getInputStream();
		int num = 0;
		byte[] buf_in = new byte[1024];
		num = is.read(buf_in);
		System.out.println(new String(buf_in,0,num));

		fis.close();
		s.close();

	}
}

class Server_Thread implements Runnable{
	private Socket s;
	Server_Thread(Socket s){
		this.s = s;
	}
	public void run(){
		String ip = s.getInetAddress().getHostAddress();
		try{
			System.out.println(ip+".....connect");

			InputStream is = s.getInputStream();

			File file = new File(ip+".jpg");
			FileOutputStream fos = new FileOutputStream(file);
			
			byte[] buf = new byte[1024];
			int len = 0;
			while((len = is.read(buf))!= -1){
				fos.write(buf,0,len);
			}
			OutputStream os = s.getOutputStream();
			os.write("send picture seccessful".getBytes());

			fos.close();
			s.close();
		}catch(Exception e){
			throw new RuntimeException("erro");		
		}
	}
}

class Server{
	public static void main(String[] args) throws Exception{
		ServerSocket ss = new ServerSocket(8086);

		while(true){
			Socket s = ss.accept();
			new Thread(new Server_Thread(s)).start();
		}
	}
}

运行结果:一张图片被上传到指定位置


我们天天回去各种论坛,常常会在某个网站登录下面我们就来下一个模拟登录的小项目

eg:项目实践5多客户端并发登录

class Client{
	public static void main(String[] args)throws Exception{
		Socket s = new Socket("100.64.182.196.",8080);

		BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
		PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
		BufferedReader bufr_socket = new BufferedReader(new InputStreamReader(s.getInputStream()));
		
		for(int i = 0;i<=2;i++){
			String line = bufr.readLine();
			if(line == null)
				break;
			pw.println(line);
			String info = bufr_socket.readLine();
			System.out.println(info);
			if(info.contains("login succeed"))
				break;
		}
		s.close();
		bufr.close();
	}
}

class Server_Thread implements Runnable{
	private Socket s;
	Server_Thread(Socket s){
		this.s = s;
	}
	public void run(){
		String ip = s.getInetAddress().getHostAddress();
		System.out.println(ip+"...connect");
		try{
			for(int i=0;i<3;i++){
				BufferedReader bufr = new BufferedReader(new InputStreamReader(s.getInputStream()));
				PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
				
				BufferedReader bufr_file = new BufferedReader(new FileReader("a.txt"));

				String str = null;
				String str_Client = bufr.readLine();
				if(str_Client == null)
					break;
				
				boolean flag = false;
				while((str = bufr_file.readLine())!= null){
					if(str_Client.equals(str)){
						flag = true;
						break;
					}	
				}
				if(flag){
					System.out.println(str_Client+"  had login");
					pw.println(str_Client+"  login succeed");
					break;
				}
				else{
					System.out.println(str_Client+"  try to login");
					pw.println(str_Client+"  is no exist");
				}
			}
			s.close();

		}catch(Exception e){
			throw new RuntimeException("server error");
		}
	}
}
class Server{
	public static void main(String[] atgs)throws Exception{
		ServerSocket ss = new ServerSocket(8080);

		while(true){
			Socket s = ss.accept();
			new Thread(new Server_Thread(s)).start();
		}
	}
}
运行结果:




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值