网络通信–你画我猜

网络通信–你画我猜

1. 服务器和客户端的连接

首先在服务器生成一个ServerSocket类型的对象(包括端口编号),等待socket对象与之连接(ServerSocketaccept()方法从连接请求队列中取出一个客户的连接请求,然后创建与客户连接的Socket对象,并将它返回。如果队列中没有连接请求 accept() 方法就会一直等待,直到接收到了连接请求才返回。);在客户端生成一个Socket对象(包括网络IP地址和端口号)。二者连接成功则可进行后续操作。

//服务器类中
private ServerSocket serverSocket;
public Socket connect(int port){
        Socket socket = null;
        try {
            serverSocket = new ServerSocket(port);
            //进入阻塞态等待连接
            socket = serverSocket.accept();
        } catch (IOException e) {
            System.out.println("连接异常!!!");
            e.printStackTrace();
        }
        return socket;
    }
 private Socket socket;
  try {
        socket = new Socket(ip,port);
  } catch (IOException e) {
        e.printStackTrace();
  }

2. 设置界面及监听器

设置界面

private JFrame initui(Socket socket){
        String[] btnstr = {"直线","矩形","圆形"};
        //创建窗体对象并配置属性
        JFrame jFrame = new JFrame("服务器");
        jFrame.setSize(400,400);
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.setLocation(500,100);
        jFrame.setLayout(new FlowLayout());
        //创建监听器对象
        ServerListener serverListener = null;
        jFrame.setVisible(true);

        try {
       		serverListener = new ServerListener(jFrame.getGraphics(),socket.getOutputStream());
       		//给窗体添加鼠标监听器
            jFrame.addMouseListener(serverListener);
        } catch (IOException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < btnstr.length; i++) {
            JButton jButton = new JButton(btnstr[i]);
            //给窗体添加按钮
            jFrame.add(jButton);	
            //给按钮添加动作监听器				
            jButton.addActionListener(serverListener);
        }
        jFrame.setVisible(true);
        //返回窗体对象
        return jFrame; 				
    }

设置监听器

public class ServerListener implements MouseListener, ActionListener {//包含鼠标监听器和动作监听器
    int x1,x2,y1,y2,x11,x22,y11,y22;
    Graphics graphics;
    OutputStream outputStream;
    String shapetype = "";
    ArrayList<Integer> pointlist = new ArrayList();
    //构造函数:传入画笔和输出流
    public ServerListener(Graphics graphics, OutputStream outputStream){
        this.graphics = graphics;
        this.outputStream = outputStream;
    }
    @Override
    public void mouseClicked(MouseEvent e) {}

    @Override
    public void mousePressed(MouseEvent e) {
         x1 = e.getX();
         y1 = e.getY();
    }

    @Override
    public void mouseReleased(MouseEvent e) {
         x2 = e.getX();
         y2 = e.getY();
        //由于是一个个byte的传输,再次防止信息内容大于一个byte的范围。例如x1=300,则传输时值会变为44(300-256);
        //因此需传输x1=x1+x11*256=44+1*256=300
         x11=x1/256;
         y11=y1/256;
         x22=x2/256;
         y22=y2/256;
		//根据命令绘制图形
         if (shapetype.equals("直线")){		
                graphics.drawLine(x1,y1,x2,y2);
         }else if (shapetype.equals("矩形")){
                graphics.drawRect(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x2-x1),Math.abs(y2-y1));
         }else if (shapetype.equals("圆形")){
             graphics.drawOval(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x2-x1),Math.abs(y2-y1));
         }
        //网络协议:[图形类型长度][图形类型][图形坐标长度][图形坐标]
        try {
            //传输图形的类型的长度
            outputStream.write(shapetype.length());
            //传输图形的类型
            outputStream.write(shapetype.getBytes(StandardCharsets.UTF_8));
            //将图形的坐标信息添加到链表中
            pointlist.add(x1);
            pointlist.add(y1);
            pointlist.add(x2);
            pointlist.add(y2);
            pointlist.add(x11);
            pointlist.add(y11);
            pointlist.add(x22);
            pointlist.add(y22);
            //传输链表的长度
            outputStream.write(pointlist.size());
            for (int i = 0; i < pointlist.size(); i++) {
                //依次传输链表内的数据信息
                outputStream.write(pointlist.get(i));
            }
            //清空链表,供下次使用
            pointlist.clear();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public void mouseEntered(MouseEvent e) {}

    @Override
    public void mouseExited(MouseEvent e) {}

    @Override
    public void actionPerformed(ActionEvent e) {
        //获取按钮上命令文字
        String btnstr = e.getActionCommand();
        shapetype = btnstr;			
    }
}

3. 设置客户端

客户端接收数据

private void startListenMsg(JFrame jFrame, Socket socket) {
        InputStream inputStream = null;
        Graphics g = jFrame.getGraphics();
        try {
            inputStream = socket.getInputStream();
            while (true){
                int x1, y1, x2, y2;
                //网络协议:[图形类型长度][图形类型][图形坐标长度][图形坐标]
                //读取图形类型的长度
                int length = inputStream.read();
                //读取图形类型
                byte[] shapetypear = new byte[length*3];
                inputStream.read(shapetypear);
                String typestr = new String(shapetypear);
                System.out.println("已接收 "+typestr);
                //读取图形坐标信息个数
                int datasize = inputStream.read();
                System.out.println("坐标个数 "+datasize);
                //读取图形坐标
                int[] dataarray = new int[datasize];
                for (int i = 0; i < dataarray.length; i++) {
                    dataarray[i] = inputStream.read();
                }
                //坐标的转化
                x1 = dataarray[0]+dataarray[4]*256;
                y1 = dataarray[1]+dataarray[5]*256;
                x2 = dataarray[2]+dataarray[6]*256;
                y2 = dataarray[3]+dataarray[7]*256;
                //绘制图形
                if (typestr.equals("直线")){
                    g.drawLine(x1,y1,x2,y2);
                }else if (typestr.equals("矩形")){
                    g.drawRect(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x2-x1),Math.abs(y2-y1));
                }else if (typestr.equals("圆形")){
                    g.drawOval(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x2-x1),Math.abs(y2-y1));
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

综上,服务器按照网络协议要求将信息依次发送至客户端,客户端依次接收信息,从而实现网络通信。

public class Msgserver {
    private ServerSocket serverSocket;
    //服务器构造函数
    public  Msgserver(int port){
        Socket socket = connect(port);
        JFrame drawui = initui(socket);
    }
}


public class Client {
    private Socket socket;
    //客户端构造函数
    public Client(String ip,int port) {
        try {
            socket = new Socket(ip,port);
            JFrame drawui = initui(socket);
            startListenMsg(drawui,socket);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

//先运行服务器main方法,在运行客户端main方法即可
public class ServerStart {
    public static void main(String[] args) {
        new Msgserver(20000);
    }
}

public class ClientStart {
    public static void main(String[] args) {
        new Client("127.0.0.1",20000);
    }
}

自己瞎写着玩.jpg
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值