zoukankan      html  css  js  c++  java
  • Java 利用 sockert 实现TCP编程一

    实现目的,本来是要用Java实现一个TCP的代理服务器,这里首先实现利用serverSocket来实现TCP的通讯,然后再在这个基础上实现JAVA版本的代理。

    一  实现的业务逻辑过程:

    1.  服务端开启监听

    2. 客户端通过socket连接客户端

    3. 服务端接收到客户端连接后,开启一个线程单独处理每一个客户进程。

    二  业务代码

    服务端代码:  SocketServerTest.java 

    package com.example.demo;
    
    import java.io.IOException;
    import java.net.InetAddress;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    /**
     * @author freew
     */
    public class SocketServerTest {
        public static void main(String[] args) {
            try {
                //创建一个服务器端的Socket,即ServerSocket,绑定需要监听的端口
                ServerSocket serverSocket = new ServerSocket(8888);
                Socket socket = null;
                //记录连接过服务器的客户端数量
                int count = 0;
                System.out.println("***服务器即将启动,等待客户端的连接***");
                while(true){//循环侦听新的客户端的连接
                    //调用accept()方法侦听,等待客户端的连接以获取Socket实例
                    socket = serverSocket.accept();
                    //创建新线程
                    Thread thread = new Thread(new ServerThread(socket));
                    thread.start();
    
                    count++;
                    System.out.println("服务器端被连接过的次数:"+count);
                    InetAddress address = socket.getInetAddress();
                    System.out.println("当前客户端的IP为:"+address.getHostAddress());
                }
                //serverSocket.close();一直循环监听,不用关闭连接
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    线程处理器代码:ServerThread.java

    package com.example.demo;
    
    import java.io.*;
    import java.net.Socket;
    import java.net.SocketException;
    
    public class ServerThread implements Runnable {
    
        Socket socket = null;//和本线程相关的Socket
    
        public ServerThread(Socket socket) {
            this.socket = socket;
        }
      
        public String receiveData(Socket connection) {
            String buffer = "";
            try {
                connection.setSoTimeout(2000);
                InputStream is = socket.getInputStream();
                InputStreamReader isr = new InputStreamReader(is, "UTF8");
                BufferedReader br = new BufferedReader(isr);
                String data = null;
                while ((data = br.readLine()) != null) {//循环读取客户端的信息
                    buffer += data;
                }
            } catch (SocketException e) {
                //e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                //e.printStackTrace();
            } catch (IOException e) {
                //e.printStackTrace();
            }
    
            if (buffer.length() > 0) {
                buffer = "我是服务器,客户端提交信息为:" + buffer;
            }
            return buffer;
        }
    
        @Override
        public void run() {
            while (true) {
            //要注意这里,把收数据的代码单独拿出去是很有必要的,注意,这里是消息循环 String recevieData
    = receiveData(socket); if (recevieData.length() > 0) { System.out.println(recevieData); OutputStream os = null; try { os = socket.getOutputStream(); } catch (IOException e) { e.printStackTrace(); } //输出流包装为打印流 PrintWriter pw = new PrintWriter(os); //向服务器端发送信息 //写入内存缓冲区 pw.write(String.format("%s",recevieData+"\n")); pw.flush();//刷新缓存,向服务器端输出信息 } } } }

    客户端代码:SocketClientTest.java

    package com.example.demo;
    
    import java.io.*;
    import java.net.Socket;
    import java.net.SocketException;
    import java.net.UnknownHostException;
    import java.util.Random;
    import java.util.Scanner;
    
    /**
     * @author freew
     */
    public class SocketClientTest {
    
        public static String receiveData(Socket connection) {
            String buffer = "";
            try {
                connection.setSoTimeout(2000);
                InputStream is = connection.getInputStream();
                InputStreamReader isr = new InputStreamReader(is, "UTF8");
                BufferedReader br = new BufferedReader(isr);
                String data = null;
                while ((data = br.readLine()) != null) {//循环读取客户端的信息
                    buffer += data;
                }
            } catch (SocketException e) {
                //e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                //e.printStackTrace();
            } catch (IOException e) {
                //e.printStackTrace();
            }
    
            if (buffer.length() > 0) {
                buffer = "我是客服端,服务端提交信息为:" + buffer;
            }
            return buffer;
        }
    
    
        public static void main(String[] args) throws IOException {
            try {
                //创建客户端Socket,指定服务器地址和端口
                Socket socket = new Socket("localhost", 8888);
                String msg = "";
                while (true) {
                    Scanner scan = new Scanner(System.in);
                    // 从键盘接收数据// nextLine方式接收字符串
                    System.out.println("nextLine方式接收:");
                    // 判断是否还有输入
                    if (scan.hasNextLine()) {
                        String str2 = scan.nextLine();
                        System.out.println("输入的数据为:" + str2 + "\n");
    
                        //建立连接后,获取输出流,向服务器端发送信息
                        OutputStream os = socket.getOutputStream();
                        //输出流包装为打印流
                        PrintWriter pw = new PrintWriter(os);
                        //向服务器端发送信息 //写入内存缓冲区
                        pw.write(String.format("%s", str2 + "\n"));
                        pw.flush();//刷新缓存,向服务器端输出信息
    
                        msg = receiveData(socket);
                        if (msg.length() > 0) {
                            System.out.println(msg);
                        }
                    }
    
                    msg = receiveData(socket);
                    if (msg.length() > 0) {
                        System.out.println(msg);
                    }
                }
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
        }
    }

    注意:上面的红色部分,这里要添加两次读出入流的操作,是为了输入后,很快就能看到服务端的返回消息。

    三  测试。

    启动服务端,监听 8888 

     启动客户端:连接  8888

     客户端输入:第一个消息  回车

    此时服务端接收的消息为:

     马上切换到客户端查看返回的消息:

     可以继续输入。

    四  一些坑

    1. 在java中,直接通过SOCKET进行连接,发送消息时,消息的末尾一定要加上 \n 回车符,否则,socket会认为消息还没有发完,于是就会发现,好像客户端发送了消息,服务端切收不到消息的情况。这时候真实的原因是客户端的消息其实是没有发出的。

    2. 这里没有使用线程池,实际测试过程中,发现每次启动一个线程来处理,消息发送的效率不高。

    半斤八两开始写BLOG了
  • 相关阅读:
    设计模式系列
    Python3 系列之 可变参数和关键字参数
    设计模式系列
    【HANA系列】SAP HANA ODBC error due to mismatch of version
    【FICO系列】SAP FICO FS00修改科目为未清项目管理
    【FIORI系列】SAP OpenUI5 (SAPUI5) js框架简单介绍
    【HANA系列】SAP HANA SQL获取当前日期加若干天后的日期
    【HANA系列】SAP HANA SQL获取本周的周一
    【HANA系列】SAP HANA SQL获取当前日期
    【HANA系列】SAP HANA SQL获取当前日期最后一天
  • 原文地址:https://www.cnblogs.com/freewsf/p/15539876.html
Copyright © 2011-2022 走看看