首页 > 编程语言 >TCP编程

TCP编程

时间:2023-04-07 10:23:39浏览次数:47  
标签:String 编程 System TCP println new out 客户端

TCP编程

Java中的TCP

java对TCP协议进行了封装,客户端和服务端都使用Socket代表两个的通信端口,不过客户端使用的是Socket类,服务端使用的是ServerSocket.

客户端代码示例
public class ClientDemo {
    public static void main(String[] args) throws IOException {
        //创建客户端套接字数据,参数是目的服务器的IP地址和端口
        Socket socket = new Socket("127.0.0.1",8080);
        //根据套接字创建套接字输出流
        OutputStream os = socket.getOutputStream();
        String str="今天天气好";
        //输出流写入
        os.write(str.getBytes());
        socket.close();
    }
}
服务端代码示例
public class ServerDemo {
    public static void main(String[] args) throws IOException {
        //创建一个服务器接收套接字对象,参数应该是服务器上的端口
        ServerSocket ss = new ServerSocket(8080);
        //监听客户端发送的套接字对象
        Socket socket = ss.accept();
        //根据套接字获取字节输入流
        InputStream is = socket.getInputStream();
        //操作套接字输入流
        byte[] bytes = new byte[1024];
        int len;
        while ((len= is.read(bytes))!=-1){
            System.out.println(new String(bytes,0,len));
        }
        //先开后关
        is.close();
        ss.close();
    }
}

必须先开启服务端,再开启客户端

多发多收

DataInputStream 和 DataOutputStream 是数据字节流,分别继承了FilterInputStream和FilterOutputStream,爷爷类是InputStream和OutputStream

作用

用来封装和装饰其他字节流

客户端代码示例
public class ClientDemo {
    public static void main(String[] args) {
        //JDK7的新特性,try-with-resources
        //格式: try(启用的资源) {} catch(e) {}
        //作用,自动为启用的资源关流,凡是实现了Closeable接口的,都需要关流
        try (Socket socket = new Socket("localhost",8080);){

            OutputStream os = socket.getOutputStream();

            DataOutputStream dos = new DataOutputStream(os);

            Scanner sc = new Scanner(System.in);
            System.out.println("请输入:");

            while (true){
                String next = sc.next();

                dos.writeUTF(next);
                dos.flush();

                if (next.equals("886")){
                    System.out.println("客户端停止");
                    break;
                }
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
服务端代码示例
public class ServerDemo {
    public static void main(String[] args) {
		
        
        try (ServerSocket ss = new ServerSocket(8080);
             Socket accept = ss.accept();
        ) {

            InputStream is = accept.getInputStream();

            DataInputStream dis = new DataInputStream(is);

            while (true) {
                try {
                    //报EOFException异常意味着,流已经读到末尾了
                    String s = dis.readUTF();
                    System.out.println(s);
                } catch (EOFException e) {
                    //getRemoteSocketAddress() 获取客户端IP地址
                    System.out.println(accept.getRemoteSocketAddress() + "下机了");
                    break;
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

自由发送

以上代码有个缺点,next()和readUTF()方法都会造成阻塞,这会导致信息以固定的模式发送:客户端发送--->服务端接收--->服务端发送--->客户端接收,因此应该设置两个线程,让两端发送时互不干涉。

客户端代码示例
public class ClientDemo {
    public static void main(String[] args) {

        try (Socket socket = new Socket("localhost", 8080)

        ) {
            //封装套接字输入流,用于接收数据
            DataInputStream dis = new DataInputStream(socket.getInputStream());
            //封装套接字输出流,用于发送数据
            DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
            //创建键盘输入流
            Scanner sc = new Scanner(System.in);
            System.out.println("开始聊天");

            //获取对方的IP地址,先获取原始格式,再强转成InetSocketAddress
            InetSocketAddress rsa = (InetSocketAddress) socket.getRemoteSocketAddress();
            String server = rsa.getHostString();
            //创建一个线程用来服务端发送数据,客户端接收数据,避免readUTF() 造成的阻塞问题
            new Thread() {
                @Override
                public void run() {
                    //接送数据
                    try {
                        while (true) {
                            String rMsg = dis.readUTF();
                            System.out.println("我是服务端" + server + ":" + rMsg);
                        }
                    } catch (IOException e) {
                        System.out.println("客服已下线,请为客服打分吧");
                    }
                }
            }.start();

            while (true) {
                String s = sc.nextLine();
                //发送数据
                dos.writeUTF(s);
                dos.flush();

                //当客户端输入886,终止循环
                if (s.equals("886")) {
                    System.out.println("我是客户端,我下机了");
                    break;
                } else {
                    System.out.println("我是客户端:" + s);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
服务端代码示例
public class ServerDemo {
    public static void main(String[] args) {

        try (
                //创建服务器套接字对象ServerSocket,并监听指定端口
                ServerSocket ss = new ServerSocket(8080);
                //监听客户端,并获取客户端套接字对象
                Socket accept = ss.accept();
        ) {
            //读取并接收数据
            //获取套接字输入流,接收数据
            DataInputStream dis = new DataInputStream(accept.getInputStream());
            //获取套接字输出流,发送数据
            DataOutputStream dos = new DataOutputStream(accept.getOutputStream());
            //获取对方的IP
            InetSocketAddress rsa = (InetSocketAddress) accept.getRemoteSocketAddress();
            String client = rsa.getHostString();

            Scanner sc = new Scanner(System.in);
            //创建另一个线程用来客户发送数据,服务端接收数据,避免readUTF() 造成的阻塞问题
            new Thread(() -> {
                try {
                    //循环接收数据
                    while (true) {
                        String s = dis.readUTF();
                        System.out.println("我是客户端" + client + ":" + s);
                    }
                } catch (IOException e) {
                    System.out.println("用户已下线");
                    ;
                }
            }).start();

            //循环发送
            while (true) {
                try {
                    //发送数据
                    String s1 = sc.next();
                    dos.writeUTF(s1);
                    System.out.println("我是服务端:" + s1);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

image-20230324142245390

image-20230324142310376

标签:String,编程,System,TCP,println,new,out,客户端
From: https://www.cnblogs.com/qifenku/p/17295149.html

相关文章

  • java编程中的C/S模式和B/S模式
    随着社会信息的发展,Java技术已经无处不在,无论是手机软件、手机Java游戏还是电脑软件等,只要你使用到电子产品就会碰到和Java有关的东西,更多的企业正采用Java语言开发网站,越来越多的程序员也应声而起,在学习Java的过程中总会遇到这样或那样的问题,今天千锋小编就大家分享一下在C/S模式......
  • 《3D编程模式》写书-第2次记录
    大家好,目前我已经完成了“拼接模式”、“撤销重做模式”、“ECS模式”的初稿下面会给出它们的使用场景,如果您正好能用到,请联系我提前阅读模式的初稿,欢迎大家给出反馈建议,您的大名有机会出现在《3D编程模式》的书中,感谢!我的QQ号:395976266我的微信号:chaogex这里是所有的的写书......
  • Semantic Kernel 知多少 | 开启面向AI编程新篇章
    引言在ChatGPT火热的当下,即使没有上手亲自体验,想必也对ChatGPT的强大略有耳闻。当一些人在对ChatGPT犹犹豫豫之时,一些敏锐的企业主和开发者们已经急不可耐的开展基于ChatGPT模型AI应用的落地探索。因此,可以明确预见的是,AI能力的集成将会是很多应用都将面临的第一事项,而拥有......
  • 万字详解 | Java 流式编程
    概述StreamAPI是Java中引入的一种新的数据处理方法。它提供了一种高效且易于使用的方法来处理数据集合。StreamAPI支持函数式编程,可以让我们以简洁、优雅的方式进行数据操作,还有使用Stream的两大原因:在大多数情况下,将对象存储在集合中就是为了处理它们,因此你会发现你把......
  • Linux(CentOS7) c语言编程, 多线程入栈出栈,错误:expected ‘while’ before ‘int’
    在Centos7里,编写多线程的入栈出栈时,出现这样错误提示:图片版: 文字版:[root@CentOs705-xitongbiancheng]#gcc05-24-01.pthread-cancel-pop-push.c-pthread05-24-01.pthread-cancel-pop-push.c:在函数‘func’中:05-24-01.pthread-cancel-pop-push.c:47:1:错误:expected......
  • 题目 1027: [编程入门]自定义函数处理最大公约数与最小公倍数
    题目描述写两个函数,分别求两个整数的最大公约数和最小公倍数,用主函数调用这两个函数,并输出结果两个整数由键盘输入。输入格式两个数输出格式最大公约数最小公倍数样例输入复制615样例输出复制330解题思路:欧几里得算法又称辗转相除法,用来求两......
  • 题目 1028: [编程入门]自定义函数求一元二次方程
    题目描述求方程的根,用三个函数分别求当b^2-4ac大于0、等于0、和小于0时的根,并输出结果。从主函数输入a、b、c的值。输入格式abc输出格式x1=?x2=?样例输入复制411样例输出复制x1=-0.125+0.484ix2=-0.125-0.484i解题思路:一元二次方程只含有......
  • 题目 1025: [编程入门]数组插入处理
    题目描述已有一个已正序排好的9个元素的数组,今输入一个数要求按原来排序的规律将它插入数组中。输入格式第一行,原始数列。第二行,需要插入的数字。输出格式排序后的数列样例输入178172324596210150样例输出178172324505962101......
  • 题目 1026: [编程入门]数字逆序输出
    题目描述输入10个数字,然后逆序输出。输入格式十个整数输出格式逆序输出,空格分开样例输入1234567890样例输出0987654321解题思路:1.题目要求是输入十个整数。2.所以我们定义数组长度为10就可以了。3.利用for循环输入与输出。注......
  • 题目 1024: [编程入门]矩阵对角线求和
    求一个3×3矩阵对角线元素之和。 解题思路和注意事项: 这道题还是蛮简单,首先要求求一个矩阵的主副对角线的元素和,那肯定要用到的就是多维数组。        多维数组的形式应该为:array[i][j]; 知道这个后我们开始分析题目:        先是主对角线,就是从左上到......