用java套接字socket实现两台电脑间的通信

实现效果:

一方发送简单的文字消息

发送、接收复杂的图片、音频、文档等

相互之间实现自由通信


java对网络编程的支持

前提条件:两台电脑在一个局域网内,比如连接了同一个路由器

将一台电脑作为服务端,一台作为客户端


实现中遇到的问题:

ip地址连接不上

发送的消息带有大量byte字节的空白占位符

DatagramPacket方法的重载

端口被占用


简单实现步骤:

服务端开放指定端口->客户端连接端口(需要服务端的ip地址)

客户端将要发送的内容转为流发送->服务端接受流并解析输出


注意事项:

服务端的ip地址是连接上局域网的ipv4地址,比如

用java套接字socket实现两台电脑间的通信_第1张图片

这是需要在命令行里ping一下验证是否能够请求到:

如出现下图字节流,则表示正常能请求到

用java套接字socket实现两台电脑间的通信_第2张图片

如出现下图情况,则要检查ip地址

用java套接字socket实现两台电脑间的通信_第3张图片

端口号必须是空闲的,一般随便输入比如7894、4566、3674、2467都是空闲的,否则编译会报错,改一下就行了。


先简单使用Tcp实现

服务端:

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TcpServer {
    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream is = null;
        ByteArrayOutputStream baos = null;

        try {
            //1.我的有一个地址
            serverSocket = new ServerSocket(9988);
            //2.等待客户端连接过来
            socket = serverSocket.accept();
            //3.读取客户端的信息
            is = socket.getInputStream();

            //管道流
            baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len;
            while ((len = is.read(buffer)) != -1) {
                baos.write(buffer, 0, len);
            }
            System.out.println(baos);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (baos != null) {
                    baos.close();
                }
                if (is != null) {
                    is.close();
                }
                if (socket != null) {
                    socket.close();
                }
                if (serverSocket != null) {
                    serverSocket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

客户端:

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

public class TcpClient {
    public static void main(String[] args) {
        InetAddress serverIP=null;
        Socket socket=null;
        OutputStream os=null;

        try{
            //1、要知道服务器地址,端口号
            serverIP=InetAddress.getByName("192.168.0.102");
//如果是本机之间互发就改为localhost或127.0.0.1
            int port=9988;
            //2、创建一个socket连接
              socket=new Socket(serverIP,port);
            //发送消息IO流
            os=socket.getOutputStream();
            os.write("小明在吗?".getBytes());

        }catch(Exception e){
            e.printStackTrace();
        }finally {
            try{
                if (os !=null) {
                    os.close();
                }
                if(socket!=null){
                    socket.close();
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
}

服务端启动,客户端在启动消息可以从客户端发送到服务端了。


使用Tcp传输图片等信息,客户端发送图片到服务端

服务器端可以向客户端发送接收消息

服务端:

import java.io.*;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

//为了简洁清晰,没有采取异常处理模块
public class TcpServer {
    public static void main(String[] args)throws Exception {
        //1.创建服务
        ServerSocket serverSocket=new ServerSocket(1256);
        //2.监听客户端
        Socket socket=serverSocket.accept();
        //3.读取信息
        InputStream is=socket.getInputStream();

        //文件输出新路径
        FileOutputStream fos=new FileOutputStream("src/resources/new/newkonan.jpg");
        byte[] buffer=new byte[1024];
        int len;
        while ((len=is.read(buffer))!=-1) {
            fos.write(buffer,0,len);
        }

        //通知客户端我已经接收完毕了
        OutputStream os=socket.getOutputStream();
        os.write("可以断开了".getBytes());

        //关闭资源
        fos.close();
        is.close();
        socket.close();
        serverSocket.close();
    }
}

客户端: 

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;

public class TcpClient {
    public static void main(String[] args)throws Exception{
        //1.建立连接
        Socket socket=new Socket(InetAddress.getByName("192.0.0.102"),1256);
        //2.建立一个输出流
        OutputStream os=socket.getOutputStream();
        //3.读取文件
        FileInputStream fos=new FileInputStream(new File("src/resources/konan.jpg"));
        //4.写出文件
        byte[] buffer=new byte[1024];
        int len;
        while ((len=fos.read(buffer))!=-1) {
            os.write(buffer,0,len);
        }

        //通知服务器,我已经结束了
        socket.shutdownInput();

        //确定服务器接受完毕,才能够断开连接
        InputStream inputStream=socket.getInputStream();
        ByteArrayOutputStream baos=new ByteArrayOutputStream();
        byte[] buffer=new byte[1024];
        int len;
        while ((len=inputStream.read(buffer))!=-1) {
            baos.write(buffer,0,len);
        }
        
        if(baos.toString()=="可以断开了"){
            //5.关闭资源
            fos.close();
            os.close();
            socket.close();
        }
    }
}

使用多线程建立聊天室,实际上使用Udp协议传输

接收端:

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class TalkReceive implements Runnable {
    DatagramSocket socket = null;
    private int Port;
    private String msgFrom;

    public TalkReceive(String msgFrom,int port) {
        this.msgFrom=msgFrom;
        this.Port=port;
        try {
            socket = new DatagramSocket(Port);//开放端口
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        while (true) {
            try {
                //准备接收
                byte[] data=new byte[1024];
                DatagramPacket packet = new DatagramPacket(data, 0, data.length);
                socket.receive(packet);    //接收数据包

                //过滤byte数组中的空白位置
                int k=0;
                for (byte dataum : data) {
                    if (dataum != (byte) 0) {
                        k++;
                    }
                }

                //断开连接
                byte[] datas=packet.getData();
                String receivedata=new String(datas,0,k);

                System.out.println(msgFrom+":"+receivedata);

                if(receivedata.equals("bye")){
                    break;    //监测到结束指令
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        socket.close();
    }
}

发送端:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;

public class TalkSend implements Runnable{
    DatagramSocket socket=null;
    BufferedReader reader =null;

    private String toIP;
    private int toPort;


    public TalkSend(String toIP,int toPort){
        this.toIP=toIP;
        this.toPort=toPort;

        try{
            socket=new DatagramSocket();    //建立套接字
            reader = new BufferedReader(new InputStreamReader(System.in));//从控制台读取数据
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        while (true) {
            try{
                String data=reader.readLine();
                //将控制台输入的数据转换为byte字节
                byte[] datas=data.getBytes(StandardCharsets.UTF_8);
                DatagramPacket packet=new DatagramPacket(datas,0,datas.length,new InetSocketAddress(this.toIP,this.toPort));

                socket.send(packet);    //发送数据包
                if (data.equals("bye")) {
                    break;    //结束指令
                }
            }catch(Exception e){
                    e.printStackTrace();
            }
        }
        socket.close();
    }
}

学生端:

public class TalkStudent {
    public static void main(String[] args) {
        //开启两个线程
        new Thread(new TalkSend("localhost",5678)).start(); //发送到5678端口
        new Thread(new TalkReceive("老师",8834)).start();    //开放8834端口接收消息
    }
}

老师端:

public class TalkTeacher {
    public static void main(String[] args) {
        //开启两个线程
        new Thread(new TalkSend("localhost",8834)).start(); //发送消息到8834端口
        new Thread(new TalkReceive("学生",5678)).start();    //开放5678端口接收消息
    }
}


展望:

可以使用网络编程结合前端页面实现通信功能

实现联机游戏

实现聊天群

你可能感兴趣的:(创意实现,java,udp,tcp)