黑马程序员_java_网络编程

------- android培训java培训、期待与您交流! ----------

通信协议】分为很多种,其中传输层中常见的协议就是 TCP / UDP 协议

TCP(Transmission Control Protocol)传输控制协议;是面向连接的协议,在收发数据前,必须和对方建立可靠的连接。一个TCP连接必须要经过三次对话才能建立起来

UDP:(User Data Protocol)用户数据报协议;UDP是一个非连接的协议,传输数据之前源端和终端不建立连接

UDP和TCP的区别

UDP:
1:连接:将数据及源和目的封装成数据包中,不需要建立连接。---------面向无连接。
2:数据大小:每个数据报包的大小在限制在64k内。
3:安全性:因无连接,是不可靠的协议且传送数据不稳定,易出错。数据也就有可能收不到,不可靠
4:效率:不需要建立连接,速度快,效率高。
5,应用:主要用于视频会议聊天,一些缺少点数据无关紧要,可靠性要求低,传输经济的应用。
TCP:
1:连接:需建立连接,形成传输数据的通道。
2:数据大小:在连接中进行大数据传输。
3:安全性:通过三次握手完成连接,是可靠协议,比较安全。
4:效率:因为必须建立连接,所以效率会稍低。
5:应用:主要用于一次传输大量报文的情形,如文件传输,远程登录等;
总的来说:TCP协议提供可靠的服务,UDP协议提供高效率的服务。

网络编程其实也就是Socket 编程,Socket就是为网络服务提供的一种机制, 它是通信的端点,在相互通信的程序两端都有Socket,网络通信也就是Socket 间的通信,通信产生的数据就是通过Socket间的IO流进行传输的。
我们在用java语言来进行网络通信时,我们需要对象来操作三个要素:IP地址,端口,协议
IP InetAddress类,它有两个子类:Inet4Address和Inet6Address,分别代表IPV4和IPV6。它将构造函数私有化了,所以提供了静态的方法来获取本类对象:getLocalHost()获取本机IP地址InetAddress对象。
端口 是应用程序的表示,
协议 就是 TCP / UDP 协议
UDP的发送端:
1).建立UDP的Socket服务,如果在创建对象时没有定义端口,系统会自动分配一个 未被使用的端口。
2).明确要发送的具体数据。
3).将数据封装成数据包。
4).用Socket服务和send()方法将数据包发送出去。
5).关闭Socket服务。
UDP的接收端:
1).创建Socket服务,此时必须明确一个端口,因为只有发送到这个端口的数据才 能被接收处理。
2).定义一个数据包,最大64K,用于存储接收到的数据。
3).将收到的数据存储到数据包中。
4).通过数据包的方法解析数据包中的具体数据内容。
5).关闭Socket服务。
发送端(客户端)  
import java.net.*;  
class  UdpSend{  
        public static void main(String[] args)throws Exception {  
             // 1,建立udp的socket服务。  
             DatagramSocket ds = new DatagramSocket(8888);//指定发送端口,这个可以不指定,系统会随机分配。  
             // 2,明确要发送的具体数据。  
             String text = "udp传输演示 哥们来了";  
             byte[] buf = text.getBytes();  
             // 3,将数据封装成了数据包。  
             DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("10.1.31.127"),10000);  
             // 4,用socket服务的send方法将数据包发送出去。  
             ds.send(dp);  
             // 5,关闭资源。  
             ds.close();  
        }  
}  
接收端(服务器端)  
import java.net.*;  
class UdpRece {  
        public static void main(String[] args) throws Exception{  
                // 1,创建udp的socket服务。  
                DatagramSocket ds = new DatagramSocket(10000);//必须指定,并且和上面的端口号一样!  
                // 2,定义数据包,用于存储接收到数据。先定义字节数组,数据包会把数据存储到字节数组中。  
                byte[] buf = new byte[1024];  
                DatagramPacket dp = new DatagramPacket(buf,buf.length);  
                // 3,通过socket服务的接收方法将收到的数据存储到数据包中。  
                ds.receive(dp);//该方法是阻塞式方法。  
                // 4,通过数据包的方法获取数据包中的具体数据内容,比如ip,端口,数据等等。  
                String ip = dp.getAddress().getHostAddress();  
                int port = dp.getPort();  
                String text = new String(dp.getData(),0,dp.getLength());//将字节数组中的有效部分转成字符串。  
                System.out.println(ip+":"+port+"--"+text);  
                // 5,关闭资源。  
                ds.close();  
        }  
}
TCP
有两个端点:客户端 和 服务端
客户端对应的对象是Socket,服务端对应的对象是ServerSocket,所以我们在使用 TCP协议时,实际上就是使用这两个对象。
TCP客户端的建立:
1).建立TCP的Socket服务,明确要访问的地址和端口。
2).如果连接成功,通道也就建立,Socket流也就产生了,调用Socket流中的输入 流和输出流,进行数据传输。
3).关闭Socket服务。
TCP服务端的建立:
1).创建服务端Socket服务,并监听一个端口。
2).通过accept()方法获取连接过来的客户端对象。
3).通过获取到的Socket对象中的Socket流和具体的客户端进行通讯。
4).在关闭服务时,需要先关闭客户端,再关闭服务端,服务端也可以不关。
客户端
package Udp;  
import java.io.*;  
import java.net.*;  
public class TcpClient   
{  
    public static void main(String[] args) throws Exception, IOException  
    {  
        //1、建立客户端Socket,确定服务器的IP地址和端口  
        Socket s=new Socket(InetAddress.getByName("www.baidu.com"),443);  
        //2、为了发送数据,我需要获取Socket中的输出流  
        OutputStream os=s.getOutputStream();  
        os.write("百度你好".getBytes());  
        //3、客户端接收数据,需要获取Socket中的输入流  
        InputStream is=s.getInputStream();  
        byte[] arr=new byte[is.available()];  
        int count=0;  
        count = is.read(arr);  
        String s1=new String(arr,0,count);  
        System.out.println(s1);  
        //4、关闭客户端  
        s.close();  
    }  
}  
服务端
package Udp;  
import java.io.*;  
import java.net.*;  
public class TcpServer   
{  
    public static void main(String[] args) throws IOException  
    {  
        //1、建立服务器Socket明确端口号  
        ServerSocket ss = new ServerSocket(11000);  
        //2、利用服务器Socket获取接过来的客户端Socket,用accept()方法  
        Socket s=ss.accept();  
        String st=s.getInetAddress().getHostAddress();  
        System.out.println("连接过来的客户端IP是:"+st);  
        //3、要么获取输入流,要么获取输出流  
        OutputStream os=s.getOutputStream();  
        InputStream is=s.getInputStream();  
        byte[] arr=new byte[1024*64];  
        int count =0;  
        count=is.read(arr);  
        System.out.println("客户端发送过来的消息是:"+new String(arr,0,count));  
        os.write("客户端你好啊!".getBytes());  
        //4、关闭服务端  
        s.close();  
        ss.close();  
    }  
}  
使用TCP协议完成一个客户端一个服务器。客户端从键盘输入读取一个字符串,发送到服务器。
服务器接收客户端发送的字符串,反转之后发回客户端。客户端接收并打印。
import java.net.*;
import java.io.*;
import java.util.*;
class  Test10
{
	public static void main(String[] args) throws IOException
	{
		Socket s = new Socket("192.168.1.102",10003);//建立客户端,指定IP和端口
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String str = br.readLine();//读取键盘录入
		OutputStream out = s.getOutputStream();
		out.write(str.getBytes());//将读取的数据写入流中
//.......................接收服务端返回的数据...........................................
		InputStream in = s.getInputStream();//接收流,用于读取服务端返回的数据
		byte[] buf2 = new byte[1024];//定义缓冲区
		int len1 = in.read(buf2);//读取数据,存入缓冲区
		System.out.println(new String(buf2,0,len1));//打印
	}
}
class TcpServer//服务端
	{
		public static void main(String[] args)throws Exception
		{	
			ServerSocket ss = new ServerSocket(10003);//建立服务端Socket服务,并监听一个端口
			Socket s = ss.accept();//通过accept方法获取连接过来的客户端对象
			InputStream in = s.getInputStream();//获取客户端发过来的数据,使用客户端对象的读取流来读取;
			String ip = s.getInetAddress().getHostAddress();//读取ip并打印,用来判断是否连接成功
			System.out.println(ip+"connected");
			byte[] buf = new byte[1024];//定义缓冲区
			int len = in.read(buf);//将数据读入缓冲区
			byte[] buf1 = new byte[1024];//定义一个新的缓冲区,用于翻转字符串
			for (int x = len;x>0;x--)
			{
				buf1[x-1]=buf[len-x];//翻转
			}
			//System.out.println(new String(buf1,0,len));
			OutputStream out = s.getOutputStream();//使用客户端输出流来输出
			out.write(buf1);//将翻转后的字节数组写入输出流
		}
	} 
服务器面对多个客户端同时访问的原理
服务端在面对多个客户端同时访问时,需要加入线程技术,因为如果服务器端是单线程的话,一个客户端连接进来以后,必须等这个连接断开,服务端才能执行到 accept() 方法,进行下次连接
所以服务器端会加入线程技术,当有客户端发起连接时,会为这个客户端新建一个线程,这样服务器端和客户端就能同时运行,不会影响下一个客户端的连接。
public class Server {
	public static void main(String[] args){
	try {
		//建立Socket服务
		ServerSocket ss = new ServerSocket(8998);
	    while(true){
		System.out.println("服务器已就绪,正在监听端口...");
		//获取连入Socket对象
		Socket s = ss.accept();
		//将连入的客户端Socket对象传入线程中
		new Thread(new ServerThread(s)).start();
		}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
//建立服务端线程
class ServerThread implements Runnable{
	private Socket s;
	//获取客户端Socket对象
	ServerThread(Socket s){
		this.s=s;
	}
	public void run(){
	 try {
	  String ip = s.getInetAddress().getHostAddress();
	  System.out.println(ip+"已连接");
	  //调用Socket输入流
	BufferedInputStream buin = 
			new BufferedInputStream(s.getInputStream());
	//定义客户端上传的文件名
	int count =1;
	File file = new File("E:\\c\\"+ip+"("+count+").jpg");
	while(file.exists()){
		file = new File("E:\\c\\"+ip+"("+count+++").jpg");
	}
	System.out.println(file);
	//建立输出流,关联文件
	BufferedOutputStream buout =
			 new BufferedOutputStream(new FileOutputStream(file));
		byte[] by = new byte[1024];
		int len =0;
		while((len=buin.read(by))!=-1){
			buout.write(by,0,len);
			buout.flush();
		}
		//向客户端反馈信息
		PrintWriter bw = new PrintWriter(s.getOutputStream());
		bw.println("文件上传成功");
		bw.flush();
		buout.close();
		s.close();
	}catch (IOException e) {
		e.printStackTrace();
		}
	}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值