Java简单实现UDP和TCP

TCP实现

TCP协议需要在双方之间建立连接,通过输入输出流来进行数据的交换,建立需要通过三次握手,断开需要四次挥手,保证了数据的完整性,但传输效率也会相应的降低。

简单的TCP实现

//服务端
public class TcpServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8886);  // 建立服务端,ip为本机ip,端口为8886
        Socket accept = serverSocket.accept();  // 监听客户端的连接,一旦有客户端连接,则会返回客户端对应的accept
        
        InputStream in = accept.getInputStream();   //获取到客户端的输出流
        byte b[] = new byte[1024];
        int len = in.read(b);
        System.out.println("接受到客户端数据,返回数据"+new String(b,0,len));  
        
        OutputStream out = accept.getOutputStream();  // 给客户端发送消息
        out.write("服务端已经接受".getBytes());
        
        serverSocket.close();
    }
}

// 客户端
public class TcpClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1", 8886);   // 通过Socket来建立和服务端的连接
        OutputStream out = socket.getOutputStream();   // 获取输出流(客户端输出流即向服务端输出信息)
        out.write("hello tcp Server".getBytes());  // 输出信息
        
        InputStream in = socket.getInputStream();   // 接受服务端的消息
        byte b[] = new byte[1024];
        int len = in.read(b);
        System.out.println("接受到服务器消息 : "+new String(b,0,len));   // 输出
        out.write("返回的的数据已经收到 ".getBytes());  // 向服务器返回消息
        socket.close();
    }
}

改进服务端,启用多线程来接受客户端的数据

// server
 public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8886); // 建立服务端,ip为本机ip,端口为8886
        int i=4;
        while(i>2){
            Socket accept = serverSocket.accept(); // 监听客户端的连接,一旦有客户端连接,则会返回客户端对应的accept
            
            ServerThread st = new ServerThread(accept);   // 启动线程
            Thread th = new Thread(st);
            th.start();
        }
        serverSocket.close();
    }

// thread

public class ServerThread implements Runnable {
    private Socket accept;
    public ServerThread(Socket s) {
        this.accept = s;
    }
    public void run(){
        InputStream in;
        try {
            in = accept.getInputStream();
            byte b[] = new byte[1024];
            int len = in.read(b);
            System.out.println("接受到客户端数据,返回数据" + new String(b, 0, len));
            OutputStream out = accept.getOutputStream(); // 给客户端发送消息
            out.write("服务端已经接受".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } 
    }
}

传递图片

// 服务端

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

        ServerSocket serverSocket = new ServerSocket(5555);
        Socket ss = serverSocket.accept();
        
        BufferedInputStream br = new BufferedInputStream(ss.getInputStream());

        BufferedOutputStream bw = new BufferedOutputStream(new FileOutputStream("copy.jpg"));  // 写出文件流
       
        byte b[] = new byte[1024];
        int len = 0;
 
        while ((len = br.read(b)) != -1) {   // 写出文件
            bw.write(b, 0, len);
            bw.flush();  // 别忘了刷新,要不然最后一块缓冲区字符串会缺失
        }

        BufferedWriter bw2 = new BufferedWriter(new OutputStreamWriter(ss.getOutputStream())); // 输出
        bw2.write("图片传输成功");
        bw2.flush();
        
        bw.close();
        ss.close();
    }

}


// 客户端

public class Client {
    public static void main(String[] args) throws UnknownHostException, IOException {
        Socket socket = new Socket("127.0.0.1", 5555);
        BufferedInputStream in = new BufferedInputStream(new FileInputStream("c.jpg"));

        BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream());

        byte b[] = new byte[1024];
        int len = 0;

        while ((len = in.read(b)) != -1) {
            out.write(b, 0, len);
            out.flush();    // 刷新缓冲区 要不然最后一块缓冲区字符串会缺失
        }
        
        socket.shutdownOutput();   // 关闭流以后Server段才会接收道结束字符结束接受

        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String line;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }
        
        in.close();
        socket.close();

    }

}

UDP实现

UDP是将数据打成数据包向对方发送,只关系是否发送成功,而不关心是否接收成功,传输速度快,但是可靠性低。

udp代码实现

// 发送端
public class SendDemo {
    public static void main(String[] args) throws IOException {
        DatagramSocket ds = new DatagramSocket(); // 此类表示用来发送和接收数据报包的套接字。
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // 键盘输入
        String line = null;
        while ((line = br.readLine()) != null) {
            byte[] bytes = line.getBytes();
            DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("127.0.0.1"), 10005); // 数据包对象
            ds.send(dp);
            if ("886".equals(line)) { // 当输入886时结束发送
                break;
            }
        }
        ds.close();
    }

}


// 接收端

public class ReciveDemo {
    public static void main(String[] args) throws IOException {
        DatagramSocket ds = new DatagramSocket(10005); // 建立服务端
        byte bytes[] = new byte[1024];
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length); // 建立数据包对象
        while (true) {
            ds.receive(dp); // 接受数据包
            byte[] data = dp.getData(); // 获取数据
            String str = new String(data, 0, dp.getLength());
            if ("886".equals(str)) {
                break;
            }
            System.out.println(str);
        }
        ds.close();
    }
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java成长之路

Java线程调度与线程优先级

线程调度是指系统为线程分配处理器使用权的过程,主要调度方式有两种,分别是协同式线程调度和抢占式线程调度。

712
来自专栏小灰灰

JDK容器学习之Queue:LinkedBlockingQueue

基于链表阻塞队列LinkedBlockingQueue 基于链表的无边界阻塞队列,常用与线程池创建中作为任务缓冲队列使用 I. 底层数据结构 先看一下内部定义...

1886
来自专栏人人都是极客

如何设计嵌入式系统?带你理解一个小型嵌入式操作系统的精髓

1 多任务机制 其实在单一CPU 的情况下,是不存在真正的多任务机制的,存在的只有不同的任务轮流使用CPU,所以本质上还是单任务的。但由于CPU执行速度非常快,...

2617
来自专栏无题

悲观锁与乐观锁与事务

事务针对的是行为操作而锁针对的是对象和数据; 事务是指执行行为操作的过程而锁是执行的手段。 悲观锁 悲观锁(Pessimistic Lock), 顾名思义,就...

3197
来自专栏无题

线程安全与锁优化——深入理解JVM阅读笔记

我根据我的理解把一些关键的要点整理了出来,并对其中一些内容作了删改。 参考地址:http://www.cnblogs.com/pacoson/p/5351355...

3345
来自专栏代码世界

Python之线程

操作系统线程理论 线程概念的引入背景 进程 之前我们已经了解了操作系统中进程的概念,程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种...

3968
来自专栏用户2442861的专栏

socket阻塞与非阻塞,同步与异步I/O模型

作者:huangguisu 原文出处:http://blog.csdn.net/hguisu/article/details/7453390

371
来自专栏美团技术团队

Linux与JVM的内存关系分析

引言 在一些物理内存为8g的服务器上,主要运行一个Java服务,系统内存分配如下:Java服务的JVM堆大小设置为6g,一个监控进程占用大约600m,Linux...

4496
来自专栏码洞

求不更学不动之Redis5.0新特性Stream尝鲜

Redis5.0最近被作者突然放出来了,增加了很多新的特色功能。而Redis5.0最大的新特性就是多出了一个数据结构Stream,它是一个新的强大的支持多播的可...

886
来自专栏Java帮帮-微信公众号-技术文章全总结

Java基础-26(01)总结网络编程

1:网络编程(理解) (1)网络编程:用Java语言实现计算机间数据的信息传递和资源共享 (2)网络编程模型 (3)网络编程的三要素 A:IP地址 ...

3398

扫码关注云+社区