Socket,IO(一)

初识socket简单创简单你server连接

基于tcp协议,建立稳定性连接的点对点通信。
实时、快速。安全性高、占用系统资源多。效率低
“请求-响应” 模式
客户端:在网络通讯中,第一次主动发起通讯的程序被称作客户端(client)程序
服务器:第一次通讯中等待连接的程序被称作服务器端(Server)程序
Socket:发送TCP消息
ServerSocket:创建服务器
套接字:是一种进程间的数据交换机制。这些进程既可以在同一机器上,也可以在网络连接的不通机器上
换句话说,套接字起到通信端点的作用。单个套接字是一个端点,而一对套接字则构成了一个双向通信信道
使非关联进程可以在本地或通过网络进行数据交换。一旦建立套接字连接,数据即可在相同或不通的系统中双向或单项发送,
直到其中一个端点关闭连接。

简单的Socket连接
server端:

    public class Server{
        public static void main(String[] args) throws IOException {
            //1.创建 服务器制定端口
            ServerSocket server = new ServerSocket(8888);
            //2.接收客户端连接,阻塞式(表示没有客户端接入不会向下运行)
            Socket socket = server.accept();
            System.out.println("一个客户端进行了连接!");
        }
    }

client端:

    public class Client {
        //使用下面方式进行简单的连接:一直端口和ip进行连接
        Socket client = new Socket("localhost", 8888);
    }

先运行server中的main方法,然后运行client重的main方法,
在服务器端的控制台会打印:

一个客户端进行连接字样

使用DataInputStream和DataOutputStream流传输

客户端代码:

    public class Client {

        public static void main(String[] args) throws UnknownHostException, IOException {
        //1.创建客户端,必须制定服务器+端口  
        Socket client = new Socket("localhost", 8888);

        //2.接收数据
        /*
        BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
        String echo = br.readLine();//阻塞式方法   分行接收不会报错(解决方法:在server的传输字符串可以+  /r/n   或者在 write方法后面+newLine())
        System.out.println(echo);
        */

        DataInputStream da = new DataInputStream(client.getInputStream());
        String re = da.readUTF();
            System.out.println(re);

        }
    }

服务器端:
使用while死循环使server一直在与你系那个状体,(后续会改进,使用多线程进行开发)

    public class Server{
        public static void main(String[] args) throws IOException {

            //1.创建 服务器制定端口
            ServerSocket server = new ServerSocket(8888);
            //2.接收客户端连接,阻塞式
            while(true){
                //死循环,一个accrpt一个客户端
                Socket socket = server.accept();
                System.out.println("一个客户端进行了连接!");
                //3.发送数据
                String msg = "欢迎使用";
                //输出流    输出流和输入流是成对的
            /*
            BufferedWriter bw = new BufferedWriter(
                    new OutputStreamWriter(
                            socket.getOutputStream()));
            bw.write(msg);
            bw.newLine();
            bw.flush();
            */
                DataOutputStream da = new DataOutputStream(socket.getOutputStream());
                da.writeUTF(msg);
                da.flush();
            }
        }
    }

这其中的BufferedWriter 和BufferedReader 不推荐使用

运行方式,首先运行Server中的main方法,控制台会显示
启动main之后的运行状态
之后运行client的main方法
这里写图片描述

表示接收到server传过来的数据

使用InputStream和OutputStream传输

和使用DataInputStream和DataOutputStream类似,

server端:

    public class Server {
    public static void main(String[] args) throws IOException {

        //1.创建 服务器制定端口
            ServerSocket server = new ServerSocket(8888);
            //2.接收客户端连接,阻塞式
            while(true){
                //死循环,一个accrpt一个客户端
                Socket socket = server.accept();
                System.out.println("一个客户端进行了连接!");
                //3.发送数据
                String msg = "欢迎使用";
                OutputStream os = socket.getOutputStream();
                try {
                    byte[] by = LoUtils.hexStr2Bytes(LoUtils.str2HexStr(msg)); //传入shuju 
                    String len = "0000" + by.length;
                    len = len.substring(len.length() - 4);
                    byte[] lenlen = len.getBytes("UTF-8");
                    byte[] true_body = LoUtils.assemble(lenlen,by);
                    os.write(true_body);
                    os.flush();
                } catch (Exception e) {
                }
            }
        }
    }

client端:

    public class Client {
        public static void main(String[] args) throws UnknownHostException, IOException {
            //1.创建客户端,必须制定服务器+端口  
            Socket client = new Socket("localhost", 8888);
            //2.接收数据
            byte[] lenbtyte = new byte[4];
            input.read(lenbtyte, 0, 4);
            int resplen = Integer.parseInt(new String(lenbtyte, "UTF-8"));
            byte[] pack = new byte[resplen];
            input.read(pack, 0, resplen);
            String res = new String(pack, "UTF-8");
            System.out.println(res);

        }
    }

运行成功后和上面的结果相同,就表示正确了。

工具类LoUtils:

    public class LoUtils {
        //2进制到16进制Str转换
        public static String str2HexStr(String str) throws Exception {
            char[] chars = "0123456789ABCDEF".toCharArray();
            StringBuilder sb = new StringBuilder("");
            byte[] bs = str.getBytes("UTF-8");
            int bit;
            for (int i = 0; i < bs.length; i++) {
                bit = (bs[i] & 0x0f0) >> 4;
                sb.append(chars[bit]);
                bit = bs[i] & 0x0f;
                sb.append(chars[bit]);
            }
            return sb.toString();
        }

        /**
        * 十六进制字符串转换成bytes
         * 
         * @param src
         * @return
         */
        public static byte[] hexStr2Bytes(String src) {
            int m = 0, n = 0;
            int l = src.length() / 2;
            byte[] ret = new byte[l];
            for (int i = 0; i < l; i++) {
                m = i * 2 + 1;
                n = m + 1;
                ret[i] = uniteBytes(src.substring(i * 2, m), src.substring(m, n));
            }
            return ret;
        }

        //转换成 已只长度的 数组段 
        public static byte[] assemble(byte[]... b) throws Exception {
            int length = 0;
            for (byte[] bl : b) {
                if (bl != null)
                    length += bl.length;
            }
            byte[] data = new byte[length];
            int count = 0;
            for (int i = 0; i < b.length; i++) {
                if (b[i] != null) {
                    System.arraycopy(b[i], 0, data, count, b[i].length);
                    count += b[i].length;
                }
            }
            return data;
        }
    }

本人相对比较习惯使用DataInputStream和DataOutputStream
传输比较简单容易理解。

Tips:亲测上述方法可用特此分享

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值