Java—— TCP协议(相关代码实现以及相关优化)

代码运行的时候先运行服务端,然后在运行客户端

 * TCP协议:
 * 1,客户端
 *      创建Socket连接服务器(指定IP地址,端口号)通过IP地址找到对应的服务器
 *      调用Socket的getInputStream()和getOutputStream()方法获取和服务器端相连的IO流
 *      输入流可以读取服务器端输出流写出的数据
 *      输出流可以写出数据到服务端的输入流
 * 
 * 2,服务端
 *      创建ServerSocket(需要指定端口号)
 *      调用ServerSocket的accept()方法接受一个客户端请求,得到一个Socket
 *      调用Socket的getInputStream()和getOutputStream()方法获取和客户端相连的IO流
 *      输入流可以读取客户端输出流写出的数据
 *      输出流可以写出数据到客户端的输入流
package com.wsq.tcp;
//java com.wsq.tcp.Demo1_Client
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class Demo1_Client {
/**
 * 1,客户端
 *      创建Socket连接服务器(指定IP地址,端口号不超过65535)通过IP地址找到对应的服务器
 *      调用Socket的getInputStream()和getOutputStream()方法获取和服务器端相连的IO流
 *      输入流可以读取服务器端输出流写出的数据
 *      输出流可以写出数据到服务端的输入流
 * @throws IOException 
 * @throws UnknownHostException 
 * 
 * 
 * */
    public static void main(String[] args) throws UnknownHostException, IOException {

        Socket wsq = new Socket("192.168.1.182",1014);  //创建Socket集装箱对象wsq,并且指定想要发送他人的IP,和对应的端口号,连接服务器

        InputStream is = wsq.getInputStream();          //获取客户端输入流
        OutputStream os = wsq.getOutputStream();        //获取客户端输入流  

        byte [] arr = new byte [1024];                  //创建字节数组用于读取服务器发来的数据
        int len = is.read(arr);                         //读取服务器发过来的数据
        System.out.println(new String (arr,0,len));     //将数据转换成字符串打印

        os.write("客户端对服务端发送请求:傻孩纸,还在睡呢?".getBytes());//客户端向服务器写数据

        wsq.close();                                    //关闭集装箱对象wsq
    }
}
package com.wsq.tcp;
//java com.wsq.tcp.Demo2_Server
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Demo2_Server {
/**
 *  * 2,服务端
 *      创建ServerSocket(需要指定端口号)
 *      调用ServerSocket的accept()方法接受一个客户端请求,得到一个Socket
 *      调用Socket的getInputStream()和getOutputStream()方法获取和客户端相连的IO流
 *      输入流可以读取客户端输出流写出的数据
 *      输出流可以写出数据到客户端的输入流
 * @throws IOException 
 * 
 * */
    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(1014);   //创建ServerSocket并且指定端口号 

        Socket wsq= server.accept();                    //接收客户端的请求,创建集装箱对象wsq,调用accept方法来接收客户端向服务端发出的请求
        InputStream is = wsq.getInputStream();          //获取客户端输入流
        OutputStream os = wsq.getOutputStream();        //获取客户端输入流  

        os.write("服务端响应客户端没,刚睡醒,不想理你".getBytes());//服务端想客户写出数据

        byte [] arr = new byte [1024];                  //创建字节数组用于接收服务器发来的数据
        int len = is.read(arr);                         //读取服务器发过来的数据
        System.out.println(new String (arr,0,len));     //将数据转换成字符串打印

        wsq.close();                                    //关闭socket集装箱
    }
}
由上面的例子可以看出,该程序有点弊端,例如:读写的时候特别费劲,写的时候得把字符串转成字节数组给写出去,读取的时候,需要创建一个字节数组,然后才能读进来,然后再转换成字符串
优化:读的时候是字符串,写的时候也是字符串,这样会简便很多

优化代码如下:

package www.wsq.TCP;
import java.io.BufferedReader;
//java com.wsq.tcp.Demo1_Client
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class Demo1_Client {
/**
 * 1,客户端
 *      创建Socket连接服务器(指定IP地址,端口号不超过65535)通过IP地址找到对应的服务器
 *      调用Socket的getInputStream()和getOutputStream()方法获取和服务器端相连的IO流
 *      输入流可以读取服务器端输出流写出的数据
 *      输出流可以写出数据到服务端的输入流
 * @throws IOException 
 * @throws UnknownHostException 
 * 
 * 
 * */
    public static void main(String[] args) throws UnknownHostException, IOException {

        Socket wsq = new Socket("192.168.1.182",1014);  //创建Socket集装箱对象wsq,并且指定想要发送他人的IP,和对应的端口号,连接服务器

        BufferedReader br = new BufferedReader(new InputStreamReader(wsq.getInputStream()));        //将字节流包装成为字符流
        PrintStream ps = new PrintStream(wsq.getOutputStream());        //PrintStream中有写出换行的方法  
        //将getInputStream()这个输入字节流和getOutputStream()这个输出字节流进行包装,包装之后,就可以直接读一行,也可以直接写出字符串,这样的话,效率会更高
        //对于getInputStream()这个输入字节流,输入想整行读,用BufferedReader,因为BufferedReader里面有ReadLine方法
        //对于getOutputStream()这个输出字节流,这里不建议用BufferedWriter进行包装,因为,BufferedWriter里面有个ReadLine方法,这个方法是以/r/n进行结束的,写完之后还得调用newLine方法
        //这里建议用一个更好的流PrintStream,对getOutputStream()这个输出字节流进行包装,该流里面有个printLine方法,这个方法使你在写出的时候直接加换行的,而且这个PrintLine方法也可以直接写字符串
        System.out.println(br.readLine());              //读出内容
        ps.println("滚,mmp");
        System.out.println(br.readLine());              //读出内容
        ps.println("呵呵,你该呗儿厉害了~");
        wsq.close();                                    //关闭集装箱对象wsq
    }

}
有常识可知,服务端是多线程的
package www.wsq.TCP;
import java.io.BufferedReader;
//java com.wsq.tcp.Demo2_Server
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Demo2_Server {
/**
 *  * 2,服务端
 *      创建ServerSocket(需要指定端口号)
 *      调用ServerSocket的accept()方法接受一个客户端请求,得到一个Socket
 *      调用Socket的getInputStream()和getOutputStream()方法获取和客户端相连的IO流
 *      输入流可以读取客户端输出流写出的数据
 *      输出流可以写出数据到客户端的输入流
 * @throws IOException 
 * 
 * */
    public static void main(String[] args) throws IOException {
        demo1();

        ServerSocket server = new ServerSocket(1014);   //创建ServerSocket并且指定端口号 
        while(true){                                    //不断地接收客户端的请求

        final Socket wsq= server.accept();              //接收客户端的请求,创建集装箱对象wsq,调用accept方法来接收客户端向服务端发出的请求
        //匿名内部类具备变量,必须被final修饰
        new Thread(){                                   //每接收到客户一条请求就开启一条线程,运用匿名内部类进行开启线程
                public void run(){
                    try {
                        BufferedReader br = new BufferedReader(new InputStreamReader(wsq.getInputStream()));        //将字节流包装成为字符流
                        PrintStream ps = new PrintStream(wsq.getOutputStream());        //PrintStream中有写出换行的方法  

                        ps.println("欢迎来到哈哈哈哈我也不知道这是哪~~");
                        System.out.println(br.readLine());              //readLine是以"\r\n"为结束标志的,没有换行该行代码就不会结束
                        ps.println("你让我怎样我就怎样,我的面子往哪放?我就不");
                        System.out.println(br.readLine());              //读出信息内容
                    } catch (IOException e) {

                        e.printStackTrace();
                    }
                }
            }.start();

            wsq.close();                                    //关闭socket集装箱
        }


    }

private static void demo1() throws IOException {
    ServerSocket server = new ServerSocket(1014);   //创建ServerSocket并且指定端口号 

    Socket wsq= server.accept();                    //接收客户端的请求,创建集装箱对象wsq,调用accept方法来接收客户端向服务端发出的请求

    BufferedReader br = new BufferedReader(new InputStreamReader(wsq.getInputStream()));        //将字节流包装成为字符流
    PrintStream ps = new PrintStream(wsq.getOutputStream());        //PrintStream中有写出换行的方法  

    ps.println("欢迎来到哈哈哈哈我也不知道这是哪~~");
    System.out.println(br.readLine());              //readLine是以"\r\n"为结束标志的,没有换行该行代码就不会结束
    ps.println("你让我怎样我就怎样,我的面子往哪放?我就不");
    System.out.println(br.readLine());


    wsq.close();                                    //关闭socket集装箱
}

}

猜你喜欢

转载自blog.csdn.net/qq_41264055/article/details/81353907
今日推荐