1.服务端单线程:
Server端:
1 package socket.demo.singlethread; 2 3 import java.io.BufferedReader; 4 import java.io.InputStream; 5 import java.io.InputStreamReader; 6 import java.net.ServerSocket; 7 import java.net.Socket; 8 9 public class Server { 10 public static void main(String[] args) { 11 try { 12 //1.定义一个ServerSocket对象进行服务端的端口注册 13 ServerSocket serverSocket = new ServerSocket(9999); 14 15 //2.监听客户端的sokcet链接请求 16 Socket socket = serverSocket.accept(); 17 18 //3.从客户端得到一个字节输入流对象 19 InputStream inputStream = socket.getInputStream(); 20 21 //4.把字节输入流包装成缓冲字节输入流 22 //BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream); 23 24 //4.把字节输入流包装成缓冲字节输入流 25 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); 26 String msg; 27 while ((msg = bufferedReader.readLine()) != null) { 28 System.out.println("服务端接收到:" + msg); 29 } 30 } catch (Exception e) { 31 e.printStackTrace(); 32 } 33 } 34 }
Client端:
1 package socket.demo.singlethread; 2 3 import java.io.IOException; 4 import java.io.OutputStream; 5 import java.io.PrintStream; 6 import java.net.Socket; 7 8 public class Client { 9 public static void main(String[] args) throws IOException { 10 //1.创建Sokcet对象请求服务端 11 Socket socket = new Socket("127.0.0.1", 9999); 12 13 //2.从Socket对象中获取一个字节输出流 14 OutputStream outputStream = socket.getOutputStream(); 15 16 //3.把字节输出流包装成打印流 17 PrintStream printStream = new PrintStream(outputStream); 18 19 //打印 20 printStream.println("hello world"); 21 22 //刷新 23 printStream.flush(); 24 } 25 }
2.服务端多线程
Server端:
1 package socket.demo.multithread; 2 3 import java.net.ServerSocket; 4 import java.net.Socket; 5 6 public class Server { 7 public static void main(String[] args) throws Exception { 8 ServerSocket serverSocket = new ServerSocket(9999); 9 while (true) { 10 Socket socket = serverSocket.accept(); 11 new ServerThreadReader(socket).start(); 12 } 13 } 14 }
线程类:
1 package socket.demo.multithread; 2 3 4 import java.io.BufferedReader; 5 import java.io.IOException; 6 import java.io.InputStream; 7 import java.io.InputStreamReader; 8 import java.net.Socket; 9 10 public class ServerThreadReader extends Thread { 11 private Socket socket; 12 13 public ServerThreadReader(Socket socket) { 14 this.socket = socket; 15 } 16 17 @Override 18 public void run() { 19 try { 20 InputStream inputStream = this.socket.getInputStream(); 21 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); 22 String msg; 23 while ((msg = bufferedReader.readLine()) != null) { 24 System.out.println(msg); 25 } 26 27 } catch (IOException e) { 28 e.printStackTrace(); 29 } 30 } 31 }
Client端:
1 package socket.demo.multithread; 2 3 import java.io.PrintStream; 4 import java.net.Socket; 5 import java.util.Scanner; 6 7 public class Client { 8 public static void main(String[] args) throws Exception { 9 Socket socket = new Socket("127.0.0.1", 9999); 10 PrintStream printStream = new PrintStream(socket.getOutputStream()); 11 Scanner scanner = new Scanner(System.in); 12 while (true) { 13 System.out.print("请输入:"); 14 String msg = scanner.nextLine(); 15 printStream.println(msg); 16 printStream.flush(); 17 } 18 } 19 }
3.使用线程池实现伪异步IO通信
Server端:
1 public class Server { 2 public static void main(String[] args) { 3 try{ 4 //1、注册端口 5 ServerSocket ss = new ServerSocket(9999); 6 7 //2、定义一个循环接受客户端的连接请求 8 //maxThreadNum:最大线程数量 9 //queueSize:任务数量 10 HandlerSocketServerPool pool = new HandlerSocketServerPool(6,10); 11 while(true){ 12 Socket socket = ss.accept(); 13 //3、把socket对象交给线程池进行处理 14 Runnable target = new ServerRunnableTarget(socket); 15 pool.execute(target); 16 } 17 } 18 catch (Exception e){ 19 e.printStackTrace(); 20 } 21 } 22 }
线程控制类:
1 public class HandlerSocketServerPool{ 2 //1、创建一个线程池变量,用来存储线程池对象 3 private ExecutorService executorService; 4 5 public HandlerSocketServerPool(int maxThreadNum,int queueSize){ 6 executorService = new ThreadPoolExecutor(3,maxThreadNum,120,TimeUnit.SECONDS,new ArrayBlockingQueue<>(queueSize)); 7 } 8 9 public void execute(Runnable target){ 10 executorService.execute(target); 11 } 12 }
线程任务类:
1 public class ServerRunnableTarget implements Runnable { 2 Socket socket; 3 4 public ServerRunnableTarget(Socket socket){ 5 this.socket = socket; 6 } 7 8 @Override 9 public void run() { 10 //这里是从socket中获取输入流,并进行打印的逻辑 11 InputStream inputStream = null; 12 try { 13 inputStream = this.socket.getInputStream(); 14 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); 15 String msg; 16 while (true) { 17 if (!((msg = bufferedReader.readLine()) != null)) break; 18 System.out.println(msg); 19 } 20 } catch (IOException e) { 21 e.printStackTrace(); 22 } 23 } 24 }
客户端:
1 public class Client { 2 public static void main(String[] args) throws IOException { 3 Socket socket = new Socket("127.0.0.1", 9999); 4 PrintStream printStream = new PrintStream(socket.getOutputStream()); 5 Scanner scanner = new Scanner(System.in); 6 while (true) { 7 System.out.print("请输入:"); 8 String msg = scanner.nextLine(); 9 printStream.println(msg); 10 printStream.flush(); 11 } 12 } 13 }
4.实现文件上传功能:
Server端:
1 public class Server { 2 public static void main(String[] args) { 3 try { 4 ServerSocket ss = new ServerSocket(9999); 5 while (true) { 6 Socket socket = ss.accept(); 7 ServerReaderThread serverReaderThread = new ServerReaderThread(socket); 8 serverReaderThread.start(); 9 } 10 } catch (Exception e) { 11 e.printStackTrace(); 12 } 13 } 14 }
线程处理类:
1 public class ServerReaderThread extends Thread { 2 private Socket socket; 3 4 public ServerReaderThread(Socket socket) { 5 this.socket = socket; 6 } 7 8 @Override 9 public void run() { 10 try { 11 DataInputStream dis = new DataInputStream(socket.getInputStream()); 12 String suffix = dis.readUTF();//读取后缀 13 System.out.println("服务端已经成功接受到了文件类型:" + suffix); 14 FileOutputStream fileOutputStream = new FileOutputStream("D:\\" + UUID.randomUUID().toString() + suffix); 15 byte[] buffer = new byte[1024]; 16 int len = 0; 17 while ((len = dis.read(buffer)) > 0) { 18 fileOutputStream.write(buffer, 0, len); 19 fileOutputStream.flush(); 20 } 21 fileOutputStream.close(); 22 System.out.println("服务端文件保存成功"); 23 } catch (Exception e) { 24 e.printStackTrace(); 25 } 26 } 27 }
Client端:
1 public class Client { 2 public static void main(String[] args) { 3 try { 4 //1、请求与服务端的Socket连接 5 Socket socket = new Socket("127.0.0.1", 9999); 6 //2、把字节输出流包装成一个数据输出流 7 DataOutputStream dos = new DataOutputStream(socket.getOutputStream()); 8 //3、先发送上传文件的后缀到服务端 9 dos.writeUTF(".txt"); 10 11 InputStream is = new FileInputStream("D:\\1.txt"); 12 byte[] buffer = new byte[1024]; 13 int len; 14 while ((len = is.read(buffer)) > 0) { 15 dos.write(buffer, 0, len); 16 } 17 dos.flush(); 18 is.close(); 19 socket.shutdownOutput();//通知服务端,数据已经发送完毕 20 } catch (Exception e) { 21 e.printStackTrace(); 22 } 23 } 24 }
补充C#版本服务端多线程,和Java的对比一下:
Server端:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Net.Sockets; 6 using System.Net; 7 using System.Threading; 8 9 namespace ServerSocket 10 { 11 class Program 12 { 13 private static byte[] m_DataBuffer = new byte[1024]; 14 //设置端口号 15 private static int m_Port = 8099; 16 static Socket serverSocket; 17 static void Main(string[] args) 18 { 19 //为了方便在本机上同时运行Client和server,使用回环地址为服务的监听地址 20 IPAddress ip = IPAddress.Loopback; 21 //实例化一个Socket对象,确定网络类型、Socket类型、协议类型 22 serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 23 //Socket对象绑定IP和端口号 24 serverSocket.Bind(new IPEndPoint(ip, m_Port)); 25 //挂起连接队列的最大长度为15,启动监听 26 serverSocket.Listen(15); 27 28 Console.WriteLine("启动监听{0}成功", serverSocket.LocalEndPoint.ToString()); 29 //一个客户端连接服务器时创建一个新的线程 30 Thread myThread = new Thread(ListenClientConnect); 31 myThread.Start(); 32 } 33 34 /// <summary> 35 /// 接收连接 36 /// </summary> 37 private static void ListenClientConnect() 38 { 39 while (true) 40 { 41 //运行到Accept()方法是会阻塞程序(同步Socket), 42 //收到客户端请求创建一个新的Socket Client对象继续执行 43 Socket clientSocket = serverSocket.Accept(); 44 clientSocket.Send(Encoding.UTF8.GetBytes("Server说:Client 你好!")); 45 //创建一个接受客户端发送消息的线程 46 Thread reciveThread = new Thread(ReciveMessage); 47 reciveThread.Start(clientSocket); 48 } 49 } 50 51 /// <summary> 52 /// 接收信息 53 /// </summary> 54 /// <param name="clientSocket">包含客户端信息的套接字</param> 55 private static void ReciveMessage(Object clientSocket) 56 { 57 if (clientSocket != null) 58 { 59 Socket m_ClientSocket = clientSocket as Socket; 60 while (true) 61 { 62 try 63 { 64 //通过clientSocket接收数据 65 int reciverNumber = m_ClientSocket.Receive(m_DataBuffer); 66 if (reciverNumber == 0) 67 { 68 m_ClientSocket.Shutdown(SocketShutdown.Both); 69 m_ClientSocket.Close(); 70 Console.WriteLine("客户端连接已断开"); 71 break; 72 } 73 Console.WriteLine("接收客户端:{0}消息:{1}", m_ClientSocket.RemoteEndPoint.ToString(), Encoding.UTF8.GetString(m_DataBuffer, 0, reciverNumber)); 74 } 75 catch (Exception ex) 76 { 77 Console.WriteLine(ex.Message); 78 m_ClientSocket.Shutdown(SocketShutdown.Both); 79 m_ClientSocket.Close(); 80 break; 81 } 82 } 83 } 84 } 85 } 86 }
Client端:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Net.Sockets; 6 using System.Net; 7 using System.Threading; 8 9 namespace ClientSocket 10 { 11 class Program 12 { 13 //创建一个数据缓冲区 14 private static byte[] m_DataBuffer = new byte[1024]; 15 static void Main(string[] args) 16 { 17 IPAddress ip = IPAddress.Loopback; 18 Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 19 20 try 21 { 22 clientSocket.Connect(new IPEndPoint(ip, 8099)); 23 Console.WriteLine("连接服务器成功"); 24 } 25 catch (Exception ex) 26 { 27 Console.WriteLine("连接服务器失败,按回车键退出"); 28 Console.WriteLine(ex.Message); 29 return; 30 } 31 //通过clientSocket接收数据 32 int receiveLength = clientSocket.Receive(m_DataBuffer); 33 Console.WriteLine("接受服务器消息:{0}", Encoding.UTF8.GetString(m_DataBuffer, 0, receiveLength)); 34 //通过clientSocket发送数据 35 for (int i = 0; i < 10; i++) 36 { 37 try 38 { 39 Thread.Sleep(1000); 40 string sendMessage = string.Format("{0} {1}", "Server 你好!", DateTime.Now.ToString()); 41 clientSocket.Send(Encoding.UTF8.GetBytes(sendMessage)); 42 Console.WriteLine("向服务器发送消息:{0}", sendMessage); 43 } 44 catch 45 { 46 clientSocket.Shutdown(SocketShutdown.Both); 47 clientSocket.Close(); 48 break; 49 } 50 } 51 Console.WriteLine("发送完毕,按回车键退出"); 52 //发送完消息后关闭连接 53 clientSocket.Shutdown(SocketShutdown.Both); 54 clientSocket.Close(); 55 Console.Read(); 56 } 57 } 58 }