Socket的应用

Socket应用

前段时间在做一个用安卓app控制机器人移动的项目,利用socket与机器人通信,控制机器人的移动并且读取机器人所返回的信息,因此学习了部分的socket知识

IP地址

  1. 为了实现网络中不同计算机之间的通信,每个机器都有一个唯一标识——IP地址(类似于手机号)
  2. IP地址的格式:数字型,如192.168.0.1(本机IP)

端口号

  1. 用处:一台主机给另一台主机发送数据被正确的应用程序接收
  2. 用于区分不同的应用程序
  3. IP地址和端口号组成了Socket,是网络运行程序之间的双向通信链路的终结点,TCP和UDP的基础。
  4. 常用的端口号:http:80 ftp:21 telnet:23

JAVA的API

  1. InetAddress:用于表示网络上的硬件资源
  2. URL:统一资源定位符,通过URL可以直接读取或者写入网络上的数据
  3. Sockets:使用TCP协议实现网络通信Socket相关类
  4. Datagram:使用UDP协议,将数据保存在数据报中,通过网络进行通信
InetAddress类
public class Test01 {
        public static void main(String args[]) throws UnknownHostException{
            InetAddress address = InetAddress.getLocalHost();
            System.out.println("计算机名" + address.getHostName());
            System.out.println("IP地址" + address.getHostAddress());
            byte[] bytes = address.getAddress();  //字节数组的形式
            System.out.println(Arrays.toString(bytes));

            //根据主机名获取InetAddress实例
            InetAddress address1 = InetAddress.getByName("asus-PC");
            System.out.println("IP地址" + address1.getHostAddress());
             }
    }
URL类
public class URLTest {
        public static void main(String args[]){
            try{
                //创建一个Url的实例
                URL imooc = new URL("http://www.imooc.com");
                //问号后面表示参数,#后面指示锚点
                URL url = new URL(imooc,"/index.html?username=tom#test");
                System.out.println("协议:"+ url.getProtocol());
                System.out.println("主机:"+url.getHost());
                //未指定端口号。则使用默认的端口,此时getPort返回-1
                System.out.println("端口号"+url.getPort());

            } catch (MalformedURLException ex){
                ex.printStackTrace();
            }

            //读取网络上的资源
            try{
                URL url1 = new URL("http://www.baidu.com");
                InputStream in = url1.openStream();

                //字节输入流转换成字符输入流,并且注意编码
                InputStreamReader inr = new InputStreamReader(in,"utf-8");
                //添加缓冲
                BufferedReader br = new BufferedReader(inr);

                String data = br.readLine();
                while (data != null){
                    System.out.println(data);
                    data = br.readLine();
                }
                //关闭
                br.close();
                inr.close();
                in.close();
            }catch (MalformedURLException ex){
                ex.printStackTrace();

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

Socket编程

步骤
  1. 创建SeverSocket 和 Socket
  2. 打开连接到Socket的输入流和输出流
  3. 按照协议对Socket进行读写操作
  4. 关闭输入流和输出流,关闭Socket
服务器端
  1. 创建SeverSocket对象,绑定监听端口
  2. 通过accept()方法监听客户端请求
  3. 连接建立后,通过输入流读客户端发送的取请求信息
  4. 通过输出流向客户端发送响应信息
  5. 关闭相关资源
客户端
  1. 创建Scoket对象,指明需要连接服务器的地址和端口号
  2. 连接建立后,通过输出流向服务器发送请求
  3. 通过输入流获取服务器的响应信息
  4. 关闭相关资源
severSocket代码示例
public class Sever {
        public static void main(String args[]){
            try{

                ServerSocket serverSocket = new ServerSocket(8899);
                System.out.println("Waiting to connect");
                Socket socket = serverSocket.accept();
                //获取输入流、读取客户端信息

                InputStream is = socket.getInputStream();
                InputStreamReader isr = new InputStreamReader(is,"utf-8");
                BufferedReader br = new BufferedReader(isr);
                String info  = null;
                while ((info  = br.readLine() )!= null){
                    System.out.println(info);
                }
                //关闭输入流
                socket.shutdownInput();
                //关闭其他资源
                br.close();
                isr.close();
                is.close();
                socket.close();
                serverSocket.close();

            }catch (IOException ex){
                ex.printStackTrace();
            }
        }
    }
client端代码示例
    public class Client {
        public static void main(String args[]){
            try {
                //指定了当前的IP地址和端口号
                Socket socket = new Socket("localhost",8899);
                //客户端向服务器发送信息,获取输出流发送信息
                OutputStream os = socket.getOutputStream();
                PrintWriter pw = new PrintWriter(os); //输出流变成打印流
                pw.write("用户名: admin;密码: 123");
                pw.flush();//刷新缓存向服务器端发送信息
                socket.shutdownOutput();//关闭输出流
                //关闭其他资源
                pw.close();
                os.close();
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
解决Socket乱码的问题
在输出端设置outputStream的文本编码
OutputStream os = socket.getOutputStream();
        OutputStreamWriter osw = new OutputStreamWriter(os,"utf-8");
        PrintWriter pw = new PrintWriter(osw); //输出流变成打印流
        pw.write("username:admin;password:123");
在SocketServe端设置接受的文本编码
InputStream is = socket.getInputStream();
    InputStreamReader isr = new InputStreamReader(is,"utf-8");
    BufferedReader br = new BufferedReader(isr);
多线程的Socket编程
创建一个Thread
    public class SeverThread extends Thread {
        Socket socket = null;
        public SeverThread(Socket socket){
            this.socket = socket;
        }

        public void run(){
            //获取输入流、读取客户端信息
            InputStream is = null;
            InputStreamReader isr = null;
            BufferedReader br = null;
            OutputStream os = null;
            OutputStreamWriter osw = null;
            PrintWriter pw = null;
            try {
                is = socket.getInputStream();
                isr = new InputStreamReader(is, "utf-8");
                br = new BufferedReader(isr);
                String info = null;
                while ((info = br.readLine()) != null) {
                    System.out.println(info);
                }
                //关闭输入流
                socket.shutdownInput();

                //获取输出流
                os = socket.getOutputStream();
                osw = new OutputStreamWriter(os, "utf-8");
                pw = new PrintWriter(osw);
                pw.write("欢迎登陆");
                pw.flush();
            }catch (IOException ex){
                ex.printStackTrace();
            }finally {
                //关闭其他资源
                try {
                    if (pw != null) {
                        pw.close();
                    }
                    if (osw != null) {
                        osw.close();
                    }
                    if (os != null) {
                        os.close();
                    }
                    if(br != null) {
                        br.close();
                    }
                    if (isr != null) {
                        isr.close();
                    }
                    if (is != null) {
                        is.close();
                    }
                    if (socket != null) {
                        socket.close();
                    }
                }catch (IOException ex){
                    ex.printStackTrace();
                }
            }
        }
    }
创建一个Sever用死循环监听
public class Sever2 {
        public static void main(String args[]) {
            try {
                ServerSocket serverSocket = new ServerSocket(8899);
                System.out.println("Waiting to Connect");
                Socket socket = null;
                int count =0 ;  //计算客户端的数量
                while (true){
                    socket = serverSocket.accept();
                    SeverThread thread = new SeverThread(socket);
                    thread.start();
                    count++;
                    System.out.println(count);
                    InetAddress address = socket.getInetAddress();
                    System.out.println("当前客户端的IP" +address.getHostAddress());
                }
            }catch (IOException ex){
                ex.printStackTrace();
            }
        }
    }

UDP编程

UDP协议以数据报作为数据传输的载体
进行数据传输时将数据定义成数据报(Datagram),并且在数据报中指明数据所要到达的Socket(主机地址和端口号),然后把数据报发送出去

所使用的工具类
  1. DatagramPacket:表示数据报包
  2. DatagramSocket:进行端到端的通信
服务器端的实现步骤
  1. 创建DatagramSocket,指定端口号
  2. 创建DatagramPacket
  3. 接收客户端发送的数据信息
  4. 读取数据
代码
public class UDPSever {
        public static void main(String args[]) throws IOException {
            DatagramSocket socket = new DatagramSocket(8899);
            //创建数据报用于接收客户端的数据存放在字节数组中
            byte [] data = new byte[1024];
            DatagramPacket packet = new DatagramPacket(data,data.length);
            //接受数据
            socket.receive(packet); //此方法接收到数据报前一直处于阻塞
            String info = new String(data,0,packet.getLength());//起始位置和末端
            System.out.println("服务器接收到:"+info);
            /**
             * 向客户端响应数据
             */
            InetAddress address = packet.getAddress();
            int port = packet.getPort();
            byte []reply = "欢迎你".getBytes();
            //创建数据报
            DatagramPacket packet1 = new DatagramPacket(reply,reply.length,address,port);
            //响应客户端
            socket.send(packet1);
            socket.close();
        }
    }
客户端实现的流程
  1. 定义发送信息
  2. 创建DatagramPacket,包含将要发送的信息
  3. 创建DatagramSocket
  4. 发送数据
代码
    public class UDPClient {
        public static void main(String args[]) throws IOException {
            InetAddress address = InetAddress.getByName("localhost");
            int port = 8899;
            byte [] data = "用户名:admin;密码:123".getBytes();
            //创建一个数据报,包含服务器的端口和信息
            DatagramPacket packet = new DatagramPacket(data,data.length,address,port);
            //创建DatagramSocket
            DatagramSocket socket = new DatagramSocket();
            socket.send(packet);

            //接受响应信息
            byte data1[] = new byte[1024];
             DatagramPacket receive = new DatagramPacket(data1,data1.length);
            socket.receive(receive);
            String s = new String(data1,0,receive.getLength());
            System.out.println("客户端接受到服务器的信息为"+s);
            socket.close();
        }
    }
UDP的多线程操作

总结

  1. 设置线程的优先级,降低
  2. 一般不需要关闭输入输出流,最终关闭Socket即可
  3. 使用TCP传输对象
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值