黑马程序员_java_网络编程
来源:互联网 发布:智业软件 编辑:程序博客网 时间:2024/06/05 07:20
-------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
- 黑马程序员_JAVA_网络编程
- 黑马程序员_JAVA_网络编程
- 黑马程序员_JAVA_网络编程
- 黑马程序员_JAVA_网络编程
- 黑马程序员_java_网络编程
- 黑马程序员_Java_网络编程
- 黑马程序员_Java_网络编程
- 黑马程序员_Java_网络编程(一)
- 黑马程序员_Java_网络编程(二)
- 黑马程序员_Java_网络编程(一)
- 黑马程序员_Java_网络编程(二)
- 黑马程序员_Java_数据类型
- 黑马程序员_Java_反射
- 黑马程序员_JAVA_基础
- 黑马程序员_JAVA_异常
- 黑马程序员_JAVA_多线程
- 黑马程序员_JAVA_字符串
- 黑马程序员_JAVA_反射
- MongoDB集群以及高可用性
- 数据模型
- 浅谈Spring事务隔离级别
- 最小二乘线性拟合
- 中西医与算法之间的联系
- 黑马程序员_java_网络编程
- 100个程序员经常去的网站转载自:http://developer.51cto.com/art/201104/255227.htm
- Redis need tcl 8.5 or newer
- admob 广告Android不显示
- Linux常用命令
- [Leetcode]String to Integer (atoi)
- Spring 事务隔离级别
- 工作过程中学到的正则表达式
- C语言中Uint8_t数据类型