当前位置:   article > 正文

Java 网络编程-Socket编程(一、简易客户端-服务器)_java socket客户端服务器端

java socket客户端服务器端

Java网络编程-Socket编程

服务器

服务器的socket程序有以下几个任务:

  • 创建ServerSocket。
  • 绑定端口。
  • 监听端口。
  • 阻塞,等待客户端连接。
  • 与客户端连接成功后,可以数据交互。

Java网络编程-Socket简介
服务器socket程序:

  1. package socket;
  2. import java.io.*;
  3. import java.net.ServerSocket;
  4. import java.net.Socket;
  5. public class Server {
  6. public static void main(String[] args) {
  7. final String QUIT = "QUIT";
  8. final int DEFAULT_PORT = 8888;
  9. ServerSocket serverSocket = null;
  10. try {
  11. // 绑定监听端口
  12. serverSocket = new ServerSocket(DEFAULT_PORT);
  13. System.out.println("启动服务器,监听端口"+DEFAULT_PORT);
  14. while(true){
  15. //等待客户端连接
  16. Socket socket = serverSocket.accept();
  17. System.out.println("客户端["+socket.getPort()+"]已连接");
  18. BufferedReader reader = new BufferedReader(
  19. new InputStreamReader(socket.getInputStream()));
  20. BufferedWriter writer = new BufferedWriter(
  21. new OutputStreamWriter(socket.getOutputStream()));
  22. String msg = null;
  23. //读取客户端发送的消息,并且进行回复
  24. while ((msg = reader.readLine()) != null){
  25. System.out.println("客户端["+socket.getPort()+"]:"+msg);
  26. //回复客户端
  27. writer.write("服务器:已收到-"+msg+"\n");
  28. writer.flush();
  29. // 查看客户端是否退出
  30. if(QUIT.equalsIgnoreCase(msg)){
  31. System.out.println("客户端["+socket.getPort()+"]已退出");
  32. break;
  33. }
  34. }
  35. }
  36. } catch (IOException e) {
  37. e.printStackTrace();
  38. } finally {
  39. if(serverSocket != null){
  40. try {
  41. serverSocket.close();
  42. System.out.println("关闭serverSocket");
  43. } catch (IOException e) {
  44. e.printStackTrace();
  45. }
  46. }
  47. }
  48. }
  49. }

创建socket、绑定端口、监听端口

创建ServerSocket、绑定端口、监听端口其实在我们的程序中,一行语句就实现了。

serverSocket = new ServerSocket(DEFAULT_PORT);

按住CTRL,进入该构造器。
源码如下:

  1. public ServerSocket(int port) throws IOException {
  2. this(port, 50, null);
  3. }

 进入再次调用的构造器。
源码如下:

  1. public ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException {
  2. setImpl();
  3. if (port < 0 || port > 0xFFFF)
  4. throw new IllegalArgumentException(
  5. "Port value out of range: " + port);
  6. if (backlog < 1)
  7. backlog = 50;
  8. try {
  9. bind(new InetSocketAddress(bindAddr, port), backlog);
  10. } catch(SecurityException e) {
  11. close();
  12. throw e;
  13. } catch(IOException e) {
  14. close();
  15. throw e;
  16. }
  17. }

进入bind方法
源码如下:

  1. public void bind(SocketAddress endpoint, int backlog) throws IOException {
  2. if (isClosed())
  3. throw new SocketException("Socket is closed");
  4. if (!oldImpl && isBound())
  5. throw new SocketException("Already bound");
  6. if (endpoint == null)
  7. endpoint = new InetSocketAddress(0);
  8. if (!(endpoint instanceof InetSocketAddress))
  9. throw new IllegalArgumentException("Unsupported address type");
  10. InetSocketAddress epoint = (InetSocketAddress) endpoint;
  11. if (epoint.isUnresolved())
  12. throw new SocketException("Unresolved address");
  13. if (backlog < 1)
  14. backlog = 50;
  15. try {
  16. SecurityManager security = System.getSecurityManager();
  17. if (security != null)
  18. security.checkListen(epoint.getPort());
  19. getImpl().bind(epoint.getAddress(), epoint.getPort());
  20. getImpl().listen(backlog);
  21. bound = true;
  22. } catch(SecurityException e) {
  23. bound = false;
  24. throw e;
  25. } catch(IOException e) {
  26. bound = false;
  27. throw e;
  28. }
  29. }

其中有两行语句如下:

  1. getImpl().bind(epoint.getAddress(), epoint.getPort());
  2. getImpl().listen(backlog);

很清楚了吧,程序调用了ServerSocket的构造器,创建了ServerSocket。
而该构造器间接实现了绑定端口、监听端口(上面两行语句)。

阻塞,等待客户端连接

Socket socket = serverSocket.accept();
可以自己去看看源码。
有客户端连接成功后,会生成一个socket

  1. BufferedReader reader = new BufferedReader(
  2. new InputStreamReader(socket.getInputStream()));
  3. BufferedWriter writer = new BufferedWriter(
  4. new OutputStreamWriter(socket.getOutputStream()));

获取向客户端读、写的字符流。

  1. String msg = null;
  2. //读取客户端发送的消息,并且进行回复
  3. while ((msg = reader.readLine()) != null){
  4. System.out.println("客户端["+socket.getPort()+"]:"+msg);
  5. //回复客户端
  6. writer.write("服务器:已收到-"+msg+"\n");
  7. writer.flush();
  8. // 查看客户端是否退出
  9. if(QUIT.equalsIgnoreCase(msg)){
  10. System.out.println("客户端["+socket.getPort()+"]已退出");
  11. break;
  12. }
  13. }

上面是服务器读取客户端发送的消息的代码,一行一行的读取消息,并且只有当客户端发送“quit”给服务器时,才表示此客户端要退出,并且在这个过程中其他客户端是不能与服务器进行连接的,因为服务器一直在while里面读取此客户端发送的数据,不过,这只是一个体验版,以后会一步一步进行升级的,毕竟学习也是一步一步学出来的。

关闭资源

先不用纠结关闭资源的正确姿势,这是课程中讲师关闭资源的方法,等基础比较好以后,我会自己去实践一下,再进行总结,之后也会去阅读源码,写相关博客,现在的任务就是把整个流程搞明白即可,不去纠结细节,一层一层来揭开Java网络编程的面纱。

serverSocket.close();

客户端

客户端的socket程序有以下几个任务:

  • 创建Socket。
  • 连接服务器。
  • 与服务器连接成功后,可以数据交互。

客户端socket程序:

  1. package socket;
  2. import java.io.*;
  3. import java.net.Socket;
  4. public class Client {
  5. public static void main(String[] args){
  6. final String QUIT = "QUIT";
  7. final String DEFAULT_SERVER_HOST = "127.0.0.1";
  8. final int DEFAULT_PORT = 8888;
  9. Socket socket = null;
  10. BufferedWriter writer = null;
  11. try {
  12. //创建socket
  13. socket = new Socket(DEFAULT_SERVER_HOST , DEFAULT_PORT);
  14. //创建IO流
  15. BufferedReader reader = new BufferedReader(
  16. new InputStreamReader(socket.getInputStream()));
  17. writer = new BufferedWriter(
  18. new OutputStreamWriter(socket.getOutputStream()));
  19. //等待用户输入信息
  20. BufferedReader consoleReader = new BufferedReader(
  21. new InputStreamReader(System.in));
  22. while (true){
  23. String input = consoleReader.readLine();
  24. //发送消息给服务器
  25. writer.write(input+"\n");
  26. writer.flush();
  27. //读取服务器返回的消息
  28. String msg = reader.readLine();
  29. System.out.println(msg);
  30. // 查看用户是否退出
  31. if (QUIT.equalsIgnoreCase(input)){
  32. break;
  33. }
  34. }
  35. } catch (IOException e) {
  36. e.printStackTrace();
  37. } finally {
  38. if(writer != null){
  39. try {
  40. writer.close(); // 会自动flush()
  41. System.out.println("关闭socket");
  42. } catch (IOException e) {
  43. e.printStackTrace();
  44. }
  45. }
  46. }
  47. }
  48. }

创建Socket、连接服务器

socket = new Socket(DEFAULT_SERVER_HOST , DEFAULT_PORT);

进入构造器。
源码如下:

  1. /**
  2. * Creates a stream socket and connects it to the specified port
  3. * number on the named host.
  4. * <p>
  5. * If the specified host is {@code null} it is the equivalent of
  6. * specifying the address as
  7. * {@link java.net.InetAddress#getByName InetAddress.getByName}{@code (null)}.
  8. * In other words, it is equivalent to specifying an address of the
  9. * loopback interface. </p>
  10. * <p>
  11. * If the application has specified a server socket factory, that
  12. * factory's {@code createSocketImpl} method is called to create
  13. * the actual socket implementation. Otherwise a "plain" socket is created.
  14. * <p>
  15. * If there is a security manager, its
  16. * {@code checkConnect} method is called
  17. * with the host address and {@code port}
  18. * as its arguments. This could result in a SecurityException.
  19. *
  20. * @param host the host name, or {@code null} for the loopback address.
  21. * @param port the port number.
  22. *
  23. * @exception UnknownHostException if the IP address of
  24. * the host could not be determined.
  25. *
  26. * @exception IOException if an I/O error occurs when creating the socket.
  27. * @exception SecurityException if a security manager exists and its
  28. * {@code checkConnect} method doesn't allow the operation.
  29. * @exception IllegalArgumentException if the port parameter is outside
  30. * the specified range of valid port values, which is between
  31. * 0 and 65535, inclusive.
  32. * @see java.net.Socket#setSocketImplFactory(java.net.SocketImplFactory)
  33. * @see java.net.SocketImpl
  34. * @see java.net.SocketImplFactory#createSocketImpl()
  35. * @see SecurityManager#checkConnect
  36. */
  37. public Socket(String host, int port)
  38. throws UnknownHostException, IOException
  39. {
  40. this(host != null ? new InetSocketAddress(host, port) :
  41. new InetSocketAddress(InetAddress.getByName(null), port),
  42. (SocketAddress) null, true);
  43. }

先不去看细节,先看注释Creates a stream socket and connects it to the specified port number on the named host.。创建流套接字并将其连接到命名主机上的指定端口号。很显然,客户端调用Socket构造器,创建了Socket,并且连接了服务器(服务器已经运行的情况下)。

  1. BufferedReader reader = new BufferedReader(
  2. new InputStreamReader(socket.getInputStream()));
  3. writer = new BufferedWriter(
  4. new OutputStreamWriter(socket.getOutputStream()));

 获取向服务器读、写的字符流。

  1. //等待用户输入信息
  2. BufferedReader consoleReader = new BufferedReader(
  3. new InputStreamReader(System.in));

等待用户输入信息,并且是控制台的输入System.in

  1. while (true){
  2. String input = consoleReader.readLine();
  3. //发送消息给服务器
  4. writer.write(input+"\n");
  5. writer.flush();
  6. //读取服务器返回的消息
  7. String msg = reader.readLine();
  8. System.out.println(msg);
  9. // 查看用户是否退出
  10. if (QUIT.equalsIgnoreCase(input)){
  11. break;
  12. }
  13. }

 

向服务器发送消息,并且接收服务器的回复,也是一行一行的读取。

关闭资源

writer.close();

 

到这里,我们便实现了一个简易客户端-服务器编写。
大家也自己进行测试,应该是没问题的。

如果有说错的地方,请大家不吝赐教

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/844556?site
推荐阅读
相关标签
  

闽ICP备14008679号