public class thread { public static void main(String[] args) { new ThreadA().start(); new Thread(new RA()).start(); } } class ThreadA extends Thread { public void run() { for(int i=0;i<=100;i++){ System.out.print(i+" "); } } } class RA implements Runnable { public void run() { for(int i=0;i<=100;i++){ System.out.print(i+" "); } } }2)线程同步
同一进程的多个线程共享同一片存储空间,为了避免访问冲突的情况,JAVA提供了一种同步机制的办法,用synchronized关键字来修饰共享的代码块,确保在某个时刻只有一个线程允许执行特定的代码块。
当一个线程在访问被synchronized修饰的数据时,会将其“上锁”,阻止其他线程访问。只有当前线程访问完这部分数据后释放锁标志,其他线程才可以访问。
注意:无论synchronized关键字加在方法上还是对象上,它取得的锁都是对象,而不是把一段代码或方法当作锁。
Executors.newFixedThreadPool(int nThreads)
当nThreads=5时,意味着线程池每次只能同时执行5个线程,相应处理5个任务;
ExecutorService pool = Executors.newFixedThreadPool(5);②线程池提交
线程池提交任务的方式有两种,分别为execute()和 submit()⽅法
execute()⽅法⽤于提交不需要返回值的任务,⽆法判断任务是否被线程池执⾏成功。
submit()⽅法⽤于提交需要返回值的任务。线程池会返回⼀个future类型的对象,可通过future对象判断线程是否执行成功,获取返回值等。
Runnable task = new MyRunnable(); pool.submit(task);③线程池关闭
ThreadPoolExecutor提供了两个方法,用于线程池的关闭,分别是shutdown()和shutdownNow()
shutdown():不会立即终止线程池,而是要等所有任务缓存队列中的任务都执行完后才终止,但再也不会接受新的任务
shutdownNow():立即终止线程池,并尝试打断正在执行的任务,并且清空任务缓存队列,返回尚未执行的任务
pool.shutdown();2.TCP和UDP区别 3.TCP 1) 创建TCP服务器的基本过程
String serverName="localhost"; int serverPort = 5000; ServerSocket ss = new ServerSocket(); //创建服务器监听套接字; SocketAddress serverAddr = new InetSocketAddress(serverName,serverPort); ss.bind(serverAddr); //绑定到服务器工作地址 Socket s = ss.accept(); //监听...如果监听到客户端的连接请求,接受并返回对应的客户端套接字Socket,否则阻塞(一直监听)2) 创建TCP客户端的基本过程
String serverName="localhost"; int serverPort = 5000; Socket s = new Socket(); SocketAddress serverAddr=new InetSocketAddress(serverName,serverPort); s.connect(serverAddr);3) TCP通信基本编程实现,并掌握如何应用多线程技术实现并行通信 TCP单线程通信 服务端
String serverName="localhost"; int serverPort = 5000; ServerSocket ss ; SocketAddress serverAddr=new InetSocketAddress(serverName,serverPort); ss=new ServerSocket(); //创建服务器监听套接字 ss.bind(serverAddr); //绑定到服务器工作地址 while (true){ Socket s = ss.accept(); //监听...如果监听到客户端的连接请求,接受并返回对应的客户端套接字Socket,否则阻塞(一直监听) BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream(),"UTF-8")); BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream(),"UTF-8")); BufferedReader sc = new BufferedReader(new InputStreamReader(System.in)); String msg=null; while ((msg=in.readLine())!=null){//接收客户端发过来的信息(1行)并返回,否则阻塞(等待客户发送信息过来) System.out.println(msg); if(msg.equals("bye")){ break; } String send_msg = sc.readLine(); out.write(send_msg);//回复信息给客户端,如果客户发过来的是"hi",则回复的是"echo:hi";将此信息写入到输出流 out.newline();//再将一个换行符写入到输出流 out.flush();//刷新流,确认将输出流中的数据发送出去给服务器 } sc.close(); in.close(); out.close(); s.close(); }客户端
String serverName="localhost"; int serverPort = 5000; Socket s = new Socket(); SocketAddress serverAddr=new InetSocketAddress(serverName,serverPort); s.connect(serverAddr); BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream(),"UTF-8")); BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream(),"UTF-8")); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String msg = null; while((msg=br.readLine())!=null){//从键盘读入信息(1行)并返回,否则阻塞(等待用户从键盘敲入一行) out.write(msg);//将信息写入到输出流 out.newline();//再将一个换行符写入到输出流 out.flush();//刷新流,确认将输出流中的数据发送出去给服务器 if(msg.equals("bye")){ break; } System.out.println(in.readLine()); } br.close(); in.close(); out.close(); s.close();TCP多线程通信 服务端
try (ServerSocket listenSocket = new ServerSocket()){ SocketAddress serverAddr=new InetSocketAddress("localhost",5000); listenSocket.bind(serverAddr); System.out.println("服务器启动成功!开始在localhost的5000端口侦听连接..."); while (true){ try { //2.监听端口并接收客户端的连接请求 Socket clientSocket = listenSocket.accept(); new ClientThread(clientSocket).start(); }catch (IOException ex) { System.out.println("异常信息:"+ex.getMessage()); } } } catch (IOException ex) { System.out.println("异常信息:"+ex.getMessage()); }多线程ClientThread
public class ClientThread extends Thread { Socket socket; public ClientThread (Socket socket){ this.socket = socket; } public void run(){ try( //带资源的try BufferedReader in = new BufferedReader(new InputStreamReader( socket.getInputStream())); BufferedWriter out = new BufferedWriter(new OutputStreamWriter( socket.getOutputStream())) ){ System.out.println("客户机连接成功!客户机地址和端口:"+socket.getRemoteSocketAddress()); String recv_msg=""; //从客户机接收字符串 while((recv_msg=in.readLine())!=null){ System.out.println("服务器收到字符串:"+recv_msg); //向客户机回送字符串 out.write(recv_msg); out.newline(); out.flush(); System.out.println("服务器回送字符串成功:"+recv_msg); if(recv_msg.equals("bye")){ break; } } } catch (IOException ex) { System.out.println("异常信息"+ex.getMessage()); } finally { //关闭套接字和流 try { if (socket != null) socket.close(); } catch (IOException ex) { System.out.println("异常信息"+ex.getMessage()); } } } }客户端
String serverName="localhost"; int serverPort = 5000; Socket s = new Socket(); SocketAddress serverAddr=new InetSocketAddress(serverName,serverPort); s.connect(serverAddr); BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream(),"UTF-8")); BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream(),"UTF-8")); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String msg = null; while((msg=br.readLine())!=null){//从键盘读入信息(1行)并返回,否则阻塞(等待用户从键盘敲入一行) out.write(msg);//将信息写入到输出流 out.newline();//再将一个换行符写入到输出流 out.flush();//刷新流,确认将输出流中的数据发送出去给服务器 if(msg.equals("bye")){ break; } System.out.println(in.readLine()); } br.close(); in.close(); out.close(); s.close();利用线程池去处理多线程 服务端
ExecutorService pool = null; //1.启动服务器 try (ServerSocket listenSocket = new ServerSocket()){ SocketAddress serverAddr=new InetSocketAddress("localhost",5000); listenSocket.bind(serverAddr); System.out.println("服务器启动成功!开始在localhost的5000端口侦听连接..."); pool = Executors.newFixedThreadPool(10); while (true){ try { //2.监听端口并接收客户端的连接请求 Socket clientSocket = listenSocket.accept(); //new ClientThread(clientSocket).start(); pool.submit(new ClientThread(clientSocket)); }catch (IOException ex) { System.out.println("异常信息:"+ex.getMessage()); } } } catch (IOException ex) { System.out.println("异常信息:"+ex.getMessage()); } finally{ if(pool!=null){ pool.shutdown(); } }多线程ClientThread
public class ClientThread extends Thread { Socket socket; public ClientThread (Socket socket){ this.socket = socket; } public void run(){ try( //带资源的try BufferedReader in = new BufferedReader(new InputStreamReader( socket.getInputStream())); BufferedWriter out = new BufferedWriter(new OutputStreamWriter( socket.getOutputStream())) ){ System.out.println("客户机连接成功!客户机地址和端口:"+socket.getRemoteSocketAddress()); String recv_msg=""; //从客户机接收字符串 while((recv_msg=in.readLine())!=null){ System.out.println("服务器收到字符串:"+recv_msg); //向客户机回送字符串 out.write(recv_msg); out.newline(); out.flush(); System.out.println("服务器回送字符串成功:"+recv_msg); if(recv_msg.equals("bye")){ break; } } } catch (IOException ex) { System.out.println("异常信息"+ex.getMessage()); } finally { //关闭套接字和流 try { if (socket != null) socket.close(); } catch (IOException ex) { System.out.println("异常信息"+ex.getMessage()); } } } }客户端
String serverName="localhost"; int serverPort = 5000; Socket s = new Socket(); SocketAddress serverAddr=new InetSocketAddress(serverName,serverPort); s.connect(serverAddr); BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream(),"UTF-8")); BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream(),"UTF-8")); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String msg = null; while((msg=br.readLine())!=null){//从键盘读入信息(1行)并返回,否则阻塞(等待用户从键盘敲入一行) out.write(msg);//将信息写入到输出流 out.newline();//再将一个换行符写入到输出流 out.flush();//刷新流,确认将输出流中的数据发送出去给服务器 if(msg.equals("bye")){ break; } System.out.println(in.readLine()); } br.close(); in.close(); out.close(); s.close();4)文件传输 客户端-接收端
package file_tcp; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedWriter; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.Date; public class MyFileReceiver { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub ServerSocket ss = new ServerSocket(8000); Socket s = ss.accept(); //构建套接字输入流,接收客户端数据 DataInputStream in=new DataInputStream( new BufferedInputStream( s.getInputStream())); //构建套接字输出流,以发送数据给客户端 BufferedWriter out=new BufferedWriter( new OutputStreamWriter( s.getOutputStream())); //接收文件名、文件长度 String filename=in.readUTF(); //文件名 int fileLen=(int)in.readLong(); //文件长度 //创建文件输出流 File f =new File(new Date().getTime() + "." + filename); DataOutputStream dos =new DataOutputStream( new BufferedOutputStream( new FileOutputStream(f))); byte buffer[] = new byte[8096]; int numRead = 0; int numFinished = 0; while (numFinished服务器-发送端=fileLen) {//文件接收完成? out.write("M_DONE"); //回送成功消息 System.out.println(filename +" 接收成功!"); }else { out.write("M_LOST"); //回送失败消息 System.out.println(filename +" 接收失败!") ; }//end if out.newline(); out.flush(); out.close(); s.close(); ss.close(); } }
package file_tcp; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; import java.net.UnknownHostException; public class MyFileSender { public static void main(String[] args) throws UnknownHostException, IOException { // TODO Auto-generated method stub File f = new File("A.txt"); Socket s =new Socket("localhost",8000); //构建套接字输出流,以发送数据给服务器 DataOutputStream out=new DataOutputStream( new BufferedOutputStream( s.getOutputStream())); //构建套接字输入流,接收服务器反馈信息 BufferedReader br=new BufferedReader( new InputStreamReader( s.getInputStream())); //构建文件输入流 DataInputStream in=new DataInputStream( new BufferedInputStream( new FileInputStream(f))); long fileLen=f.length(); //计算文件长度 //发送文件名称、文件长度 out.writeUTF(f.getName()); out.writeLong(fileLen); out.flush(); //传送文件内容 int numRead=0; //单次读取的字节数 int numFinished=0; //总完成字节数 byte[] buffer=new byte[8096]; while (numFinished5)Socket 与 TCP三次握手关系 客户端connect方法后触发三次握手
握手成功后,在服务器端,对应的连接会加入accept队列.服务器执行accept 方法
只从accept队列取出一个连接进行处理,因此accept 方法与三次握手无关。
4.安全通信 1)SSL的概念,协议的作用,JDK中提供的相关的主要的包及类 概念与作用SSL:安全套接字层协议 (Secure Sockets Layer,SSL),SSL提供加密,来源认证和数据完整性验证功能,为Web浏览器和TCP C/S提供安全通信。
TLS:传输层安全协议(Transport Layer Security,TLS),SSL升级版
JSSE:Java安全Socket扩展(Java Secure Sockets Extension,JSSE),使用SSL和TLS保护网络通信安全
相关类安全Socket编程的主要类与接口:
①javax.net.ssl包: SSLServerSocket(ServerSocket的子类)、
②Java.security包:
SSLSocket(Socket的子类)、
KeyManagerFactory、TrustManagerFactory、
SSLContext、SSLSocketFactory KeyStore、MessageDigest、Key等等
2)加密算法对称加密:加密和解密都使用相同的密钥,如DES、AES;
非对称加密: 加密和解密使用不同的密钥,即,密钥对(公钥、私钥),如RSA;✳用公钥加密的信息,必须用私钥才能解密;
3) 创建安全客户端与服务器Socket的过程 5.UDP UDP服务端
✳用私钥加密的信息,必须用公钥才能解密;
由于非对称算法加密计算量大,不适合大的数据量, 解决方法是:应用对称密钥加解密数据,应用非对称密钥验证和加解密对称密钥的相关信息。import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetSocketAddress; import java.net.SocketAddress; public class Server { public static void main(String[] args) { //1.启动服务器 SocketAddress sa = new InetSocketAddress("localhost",8000); try (DatagramSocket s = new DatagramSocket(sa)){ System.out.println("服务器启动成功!开始在localhost的8000端口侦听连接..."); while (true){ try { DatagramPacket pin = new DatagramPacket(new byte[512],512); s.receive(pin); String msg = new String(pin.getData(),0, pin.getLength()); System.out.println(msg); String replyMsg = "echo: " + msg; DatagramPacket pout = new DatagramPacket( replyMsg.getBytes(),replyMsg.getBytes().length,pin.getAddress(),pin.getPort()); s.send(pout); System.out.println(pin.getAddress()+":"+pin.getPort()); }catch (IOException ex) { System.out.println("异常信息:"+ex.getMessage()); } } } catch (IOException ex) { System.out.println("异常信息:"+ex.getMessage()); } } }UDP客户端import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetSocketAddress; import java.net.SocketAddress; public class Client { public static void main(String[] args) { DatagramSocket s=null; String serverName="localhost"; int serverPort = 8000; BufferedReader br=null; try{ s = new DatagramSocket(0);//系统自动分配一个端口,也可以指定一个端口 InetSocketAddress ia=new InetSocketAddress(serverName,serverPort);//服务器的地址 br = new BufferedReader(new InputStreamReader(System.in));//键盘输入 String msg = null; while ((msg = br.readLine())!=null){ DatagramPacket pout = new DatagramPacket(msg.getBytes(),msg.getBytes().length,ia); s.send(pout); DatagramPacket pin = new DatagramPacket(new byte[512],512); s.receive(pin); //socket收到的数据的长度不一定是pin包定义的数组的大小的,可以通过pin.getLength()取得接收到的数据的长度。 //将接收到的数据转换成字符串时,可以设定从包里取多少数据,如下: System.out.println(new String(pin.getData(),0, pin.getLength())); if(msg.equals("bye")){ break; } } }catch (Exception e){ e.printStackTrace(); } finally{ try { if(s!=null) s.close(); if(br!=null) br.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }6.组播组播地址:组播中的一组主机所共享的地址
组播地址是范围在224.0.0.0~239.255.255.255之间的IP地址
224.0.0.0~224.0.0.255 为预留的组播地址(永久组地址),地址224.0.0.0保留不做分配,其它地址供路由协议使用; 224.0.1.0~224.0.1.255是公用组播地址,可以用于Internet; 224.0.2.0~238.255.255.255为用户可用的组播地址(临时组地址),全网范围内有效; 239.0.0.0~239.255.255.255为本地管理组播地址,仅在特定的本地范围内有效。 组播通信过程 组播接收端package multicast; import java.net.DatagramPacket; import java.net.InetAddress; import java.net.MulticastSocket; public class MultiCastReceiver { public static void main(String[] args) { // TODO Auto-generated method stub try(MulticastSocket socket = new MulticastSocket(4000)){ InetAddress ia = InetAddress.getByName("225.0.1.1"); socket.joinGroup(ia); while(true){ DatagramPacket packet = new DatagramPacket(new byte[512],512); socket.receive(packet); String msg = new String (packet.getData(), 0, packet.getLength()); System.out.println(msg); if(msg.equals("bye")){ break; } } socket.leaveGroup(ia); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } }组播发送端package multicast; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.DatagramPacket; import java.net.InetAddress; import java.net.MulticastSocket; public class MultiCastSender { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub try(MulticastSocket socket = new MulticastSocket(4000); BufferedReader br = new BufferedReader(new InputStreamReader(System.in))){ InetAddress ia = InetAddress.getByName("225.0.1.1"); socket.joinGroup(ia); //socket.setTimeToLive(0);//如果值为0,则只能在本机传播,而1则只能在本地子网中传播 socket.setLoopbackMode(true);//参数为disable,当等于false时,组播的信息也发回自己 new SelfReceiver(socket).start();//接收自己所组播的信息 String msg = null; while ((msg=br.readLine())!=null){ DatagramPacket p = new DatagramPacket(msg.getBytes(), msg.getBytes().length, ia, 4000); socket.send(p); } socket.leaveGroup(ia); }catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } } class SelfReceiver extends Thread { MulticastSocket socket; public SelfReceiver(MulticastSocket socket){ this.socket = socket; } public void run(){ while(true){ try { DatagramPacket packet = new DatagramPacket(new byte[512],512); socket.receive(packet); String msg = new String (packet.getData(), 0, packet.getLength()); System.out.println("接收信息:" + msg); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }7.非阻塞I/O 1)服务器和客户端的基本事件 2) 判断哪种事件key.isAcceptable(): 处理接收连接就绪事件
key.isReadable(): 处理读就绪事件
key.isWritable(): 处理写就绪事件
8. 流1)分成字节流与字符流,通常图片或音频视频文件用字节流,而文本用字符流,但是如果单纯地复制或传输文本文件,则用字节流
9.HTTP:
2)基类:字节流的基类是InputStream、OutputStream,字符流是Reader、Writer,为抽象类,不能直接创建对象,
通过重载read、write方法来实现不同的读写 *** 作
3)常用的字节流类和字符流类及其方法的应用,如缓冲流,文件流,数据流
-缓冲流:输入时可以提供readline的方法读取一行字符,输入时可以直接write字符串,需要通过flush()刷新流。
-文件流:当文件不存在时,输入流会异常,而输出流则会创建文件,设置Append参数可以覆盖或追加信息
-数据流:不同数据类型的数据的读写,提供不同的方法,如readUTF, readLong…get常用于向服务器索取信息;post常用于向服务器提交信息
获取网页内容方式 1) 使用openStream方法获取网页html内容创建URL对象(给定url地址),通过调用openStream()的方法来获取资源
try { URL u = new URL("http://xxx/"); BufferedReader in = null; in = new BufferedReader( new InputStreamReader(u.openStream(),"UTF-8")); String str; while ((str= in.readLine())!=null){ System.out.println(str); } in.close(); } catch (IOException e) { e.printStackTrace(); }将会输出当前网站的HTML信息
2)利用HttpGet创建HttpGet对象(给定url地址),通过httpClient.execute(httpGet)获取资源及信息,判断状态码以进入不同的 *** 作处理。
package HTTP; import java.io.FileOutputStream; import java.io.IOException; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.util.EntityUtils; public class httpclient_getHTML { public static void main(String[] args) throws IOException { String link = "http://xxx"; String outfile = "test.html"; HttpClient httpClient = HttpClientBuilder.create().build(); HttpGet httpGet = new HttpGet(link); HttpResponse response = httpClient.execute(httpGet); int statusCode = response.getStatusLine().getStatusCode(); System.out.println(statusCode); // 对200状态码进行处理 if (statusCode == HttpStatus.SC_OK) { HttpEntity resEntity = response.getEntity(); // 获取页面数据并保存到文件 byte[] pageContent = EntityUtils.toByteArray(resEntity); FileOutputStream fout = new FileOutputStream(outfile); fout.write(pageContent); System.out.println("获取网页成功!"); } else { System.out.println("获取网页失败!"); } } }欢迎分享,转载请注明来源:内存溢出
评论列表(0条)