java 网络编程

网络编程

一、网络基础:

网络通讯:我电脑输出流对你电脑输入流,你电脑输出流对我电脑输入流,说到底是IO操作

不同设备通讯都具备一套标准,我们叫OSI参考模型。

OSI参考模型 :

物理层:主要走01代码

数据链路层:主要建立逻辑上的电路,主要的协议是PPOE,拨号上网

网络层:IP寻址,主要是路由

传输层:分用和复用  端口

会话层,表示层,应用层

TCP/IP参考模型:

网络接口层

互联层

传输层

应用层

java.net.InetAddress  此类表示互联网协议 (IP) 地址。

getLocalHost();返回本地主机。

getByName(String host);在给定主机名的情况下确定主机的 IP 地址

getAllByName(String host); 在给定主机名的情况下,根据系统上配置的名称服务返回其 IP 地址所组成的数组。

getByAddress(byte[] addr);根据提供的主机名和 IP 地址创建 InetAddress。     

java.net.URLDecoder和java.net.URLEncoder

package com.part01;
/*URL编码,把宽字节转为单字节
http默认用的就是URL编码*/
import java.net.URLDecoder;
import java.net.URLEncoder;
public class Demo01 {
	public static void main(String[] args)throws Exception {
		String str="http://localhost/s?name=李四&sex=男";
		String en=	URLEncoder.encode(str,"utf-8");
	         System.out.println(en);
        String zh=URLDecoder.decode(en, "utf-8");
	         System.out.println(zh);
	}

}

结果如下:

http%3A%2F%2Flocalhost%2Fs%3Fname%3D%E6%9D%8E%E5%9B%9B%26sex%3D%E7%94%B7
http://localhost/s?name=李四&sex=男

模拟客户端给服务器发消息

Server类:

package com.part02;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;//此类实现服务器套接字。服务器套接字等待请求通过网络传入。它基于该请求执行某些操作,然后可能向请求者返回结果
import java.net.Socket;

public class Server {

	public static void main(String[] args) throws Exception
	{
		//服务器端口为8080
		ServerSocket server=new ServerSocket(8080);
		System.out.println("服务器已起动。。。。");
		
		//accept() 侦听并接受到此套接字的连接。
		Socket  s=server.accept();//阻塞  等客户的到来
		
		 System.out.println("客户机连上了。。。。。");
		 
		 InputStream is=s.getInputStream();
		 OutputStream os=s.getOutputStream();
		 
		 BufferedReader br=new BufferedReader(new InputStreamReader(is));
		 String str=null;
		 while(null!=(str=br.readLine()))
		 {
			 System.out.println("客户机说:"+str);
		 }
		 
		 System.out.println("end........");
	}
}

Client类: 

package com.part02;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.Socket;//此类实现客户端套接字,也可以就叫“套接字”,套接字是两台机器间通信的端点。 
public class Client {
	public static void main(String[] args)throws Exception 
	{
		InetAddress ip=InetAddress.getByName("192.168.197.1");
		Socket s=new Socket(ip, 8080);//这一句如果能得到s 说明已经得到服务器了
		
		PrintStream ps=new PrintStream(s.getOutputStream());
		
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		String str=null;
		while(null!=(str=br.readLine()))
		{
			ps.println(str);
		}	
		System.out.println("client end...");
	}
}

TCP实现客户端和服务器双向聊天:

Server类:

package com.part03;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {

	public static void main(String[] args)throws Exception
	{
		ServerSocket server=new ServerSocket(8080);
		
		System.out.println("服务器启动...");
		
		Socket s=server.accept();

		new KeyThread(new PrintStream(s.getOutputStream())).start();//这句意思就是不断地读键盘,读到键盘以后,把数据发出去,发给它对应的输出流,给客户端了
		
		BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));//还要不断地读客户端发来的数据
		
		new ReadOther("Client", br).start();		
	}

}
//端口的选取范围0-65535,0-1024是系统默用端口
//服务器要不断地读客户端发来的数据,还要不断地读键盘,由键盘发出去。是用线程

KeyThread线程类 

package com.part03;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;

public class KeyThread extends Thread {

	PrintStream ps=null;
	public KeyThread(PrintStream ps)
	{
		this.ps=ps;
	}
	//线程代码。不断地读键盘
	@Override
	public void run() {
	    String str=null;
	    BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
	    try {
			while(null!=(str=br.readLine()))
			{
				ps.println(str);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	
}

ReadOther类 

package com.part03;

import java.io.BufferedReader;
import java.io.IOException;

public class ReadOther extends Thread {
	BufferedReader br ;
	private String name;
	public ReadOther(String name,BufferedReader br)
	{
		this.name=name;
		this.br=br;
	}
	@Override
	public void run() {
		String str=null;
		try {
			while(null!=(str=br.readLine()))
			{
				System.out.println(name+":"+str);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	
}

 Client类 

package com.part03;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.Socket;

public class Client {

	public static void main(String[] args) throws Exception{

     Socket soc=new Socket(InetAddress.getByName("192.168.197.1"),8080);
   
     PrintStream ps=new PrintStream(soc.getOutputStream());
     BufferedReader br=new BufferedReader(new InputStreamReader(soc.getInputStream()));
     
     new KeyThread(ps).start();
     new ReadOther("Server:", br).start();
	}

}

基于UDP编程,客户端发包,服务器收包:

Server类: 

package com.part04;

import java.net.DatagramPacket;//此类表示数据报包。可以接收也可以发送数据包
import java.net.DatagramSocket;//此类表示用来发送和接收数据报包的套接字 
/*void receive(DatagramPacket p) 从此套接字接收数据报包。
  void send(DatagramPacket p) 从此套接字发送数据报包*/
 

//用于收数据
public class Server {

	public static void main(String[] args)throws Exception {

		  DatagramSocket ds=new DatagramSocket(8080);
		  System.out.println("服务器启动........");
		  byte [] data=new byte[512];
		  //用于收数据的包
		  // DatagramPacket(byte[] buf, int length)  构造 DatagramPacket,用来接收长度为 length 的数据包。
		  DatagramPacket  dp=new DatagramPacket(data, data.length);
		  //DatagramSocket.receive(DatagramPacket p)  从此套接字接收数据报包。
		  ds.receive(dp);//阻塞 ,没有数据来的话,不往下执行
		  //  String(byte[] bytes, int offset, int length)  通过使用平台的默认字符集解码指定的 byte 子数组,构造一个新的 String。
		  System.out.println("收到了数据---"+dp.getLength()+"---"+new String(data,0,dp.getLength()));
		  
	}

}
//客户端给服务器发一个数据包,他不管服务器有没有收到,它的任务结束了,这是UDP(发快递)
//TCP叫面向连接的协议,而UDP是不需要连接,它的性能比TCP好,不过它的丢包率比较高

Client类: 

package com.part04;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class Client {
	public static void main(String[] args) throws Exception{
		 DatagramSocket ds=new DatagramSocket();
		 String str="大家好";
		 byte[]data=str.getBytes();
		 InetAddress ip=InetAddress.getByName("192.168.197.1");
		 DatagramPacket dp=new DatagramPacket(data, data.length, ip, 8080);
		 ds.send(dp);
	}
}

先启动Server,再启动Client类,结果如下:

服务器启动........
收到了数据---6---大家好

用UDP来实现双向聊天的程序 

Server类:

package com.part05;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketAddress;//此类表示不带任何协议附件的 Socket Address。
import java.net.SocketException;
/**
 * 让服务器监听8080端口,客户端是谁,他不知道,当客户端给它发一个包,它收到一个包,当他收到这个包时 他就知道这个包来自于谁,他就知道客户端的IP地址了,
 * 所以服务器要发包,它需要先收到一个包,所以使用UDP,第一次得发包,空包也行,目的时让服务器知道你的地址
 * 双方要通讯,双方是要互发信息
 * @author 0236ma
 *
 */
public class Server
{
	int port=8080;//让服务器监听8080端口,
	DatagramSocket ds=null;
	//构建两个包,一个用来发,一用来收
	DatagramPacket send=null;//发
	DatagramPacket recieve=null;//收
	
	byte [] buffer=new byte[512];//1k
	
	private BufferedReader br=null;
	
	SocketAddress sa=null;//封装了端口和IP
	
	public Server()//初始化信息
	{
		try {
			ds=new DatagramSocket(port);
			System.out.println("start server....");
			recieve=new DatagramPacket(buffer, buffer.length);
		    //先收客户端的一个包,收这个包的目的是为了知道客户端的IP地址和端口
			ds.receive(recieve);//如果这一行执行通过,说明我收到一个数据包
			
			sa=recieve.getSocketAddress();//客户端的IP地址
			
			System.out.println("收到客户端的一个包:"+new String(recieve.getData())+recieve.getAddress()+recieve.getPort());
//不断接受客户端发来的数据,不断地接收键盘上的数据,使用线程			 	
		    //读客户端发来的数据
			new Thread(new Runnable() {
				
				@Override
				public void run() {
			    
					try {
						while(true)
						{
						ds.receive(recieve);
						
						System.out.println("client说:"+new String(recieve.getData()));
						}
					} catch (IOException e) {
						e.printStackTrace();
					}
					
				}
			}).start();
			
			
		    //读键盘
			String str=null;
			br=new BufferedReader(new InputStreamReader(System.in));
			
			while(null!=(str=br.readLine()))
			{
				//写给客户端
				byte[]tem=str.getBytes();
				send=new DatagramPacket(tem, tem.length, sa);
				
				ds.send(send);//发给客户端
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public static void main(String[] args) 
	{
	    new Server();
	}
}

Client类: 

package com.part05;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

public class Client {
	int port=8080;
	DatagramSocket ds=null;
	DatagramPacket send=null;//发
	DatagramPacket recieve=null;//收
	byte [] buffer=new byte[512];
	private BufferedReader br=null;
	private InetAddress ip=null;
	public Client()
	{
		try {
			ip=InetAddress.getByName("192.168.197.1");
			ds=new DatagramSocket();//客戶端随机开一个端口,无需绑定port
			
			recieve=new DatagramPacket(buffer, buffer.length);
			byte[] hand="hi".getBytes();
			
			send=new DatagramPacket(hand, hand.length, ip, port);
			ds.send(send);
			
			     //读对方发来的数据
				 new Thread(new Runnable() {
					@Override
					public void run() {
						try {
							while(true)
							{
							ds.receive(recieve);
							System.out.println("Server:"+new String(recieve.getData()));
							}
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
				}).start();
				
			    //读键盘
				String str=null;
				br=new BufferedReader(new InputStreamReader(System.in));
				while(null!=(str=br.readLine()))
				{
					//写给客户端
					byte[]tem=str.getBytes();
					send=new DatagramPacket(tem, tem.length, ip,port);
					ds.send(send);//发给客户端
				}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public static void main(String[] args) {
          new Client();
	}
}

 

 

 

 

 

 

 

 


      


        
        

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值