Java之Socket

Wesley13
• 阅读 756
  • 介绍

网络编程是Java中很重要的一块,实现的是应用层的网络协议。本文介绍如何使用socket开发,包括有TCP和UDP的代码实现。 关于UDP广播相关的内容,可以点击这里查看另外一篇文章。 普通的Socket是使用明文来传输的,那怎么才能加密这个传输通道呢?赶快下面的例子吧。

  • TCP

下面的代码实现一个服务端监听,然后打印接收到的字符串数据,最后再给客户端返回一个字符串。 [codesyntax lang="java"]

/**
 * http://surenpi.com
 */
package org.suren.test;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;

/**
 * @author suren
 * @date 2015年9月2日 上午8:09:54
 */
public class TcpServer
{
    public static void main(String[] args) throws Exception
    {
        ServerSocket server = null;
        
        try
        {
            server = new ServerSocket(8090);
            
            while(true)
            {
                Socket client = server.accept();
                
                SocketAddress remoteAddr = client.getRemoteSocketAddress();
                InputStream input = client.getInputStream();
                OutputStream output = client.getOutputStream();
                
                System.out.println(remoteAddr);
                
                byte[] buf = new byte[1024];
                int length = -1;
                
                StringBuffer stringBuf = new StringBuffer();
                while((length = input.read(buf)) > 0)
                {
                    stringBuf.append(new String(buf, 0, length));
                    
                    if(length < buf.length)
                    {
                        break;
                    }
                }
                
                System.out.println(stringBuf.toString());
                
                output.write("done".getBytes());
                
                System.out.println("server round over.");
                
                client.close();
            }
        }
        finally
        {
            if(server != null)
            {
                server.close();
                
                System.out.println("server closed.");
            }
        }
    }
}

[/codesyntax] 下面是客户端的实现: [codesyntax lang="java"]

/**
 * http://surenpi.com
 */
package org.suren.test;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;

/**
 * @author suren
 * @date 2015年9月2日 上午8:14:42
 */
public class TcpClient
{

    /**
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException
    {
        Socket client = new Socket();

        SocketAddress addr = new InetSocketAddress("127.0.0.1", 8090);
        
        client.connect(addr);
        
        InputStream input = client.getInputStream();
        OutputStream output = client.getOutputStream();
        
        output.write("hello from client".getBytes());
        
        byte[] buf = new byte[1024];
        int length = -1;
        
        System.out.println("client write over.");
        
        StringBuffer stringBuf = new StringBuffer();
        while((length = input.read(buf)) > 0)
        {
            stringBuf.append(new String(buf, 0, length));
            
            if(length < buf.length)
            {
                break;
            }
        }
        
        System.out.println(stringBuf.toString());
        
        client.close();
    }

}

[/codesyntax]

  • UDP

这里首先要提醒的是,UDP协议是不保证数据传输的完整性的,所以说如果对数据完整性要求很高的话,不建议采用这种协议。UDP相比TCP的优点是传输效率高,可以用在视频传输上。 [codesyntax lang="java"]

/**
 * http://surenpi.com
 */
package org.suren.test;

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

/**
 * @author suren
 * @date 2015年9月2日 上午9:44:39
 */
public class UdpServer
{

    /**
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException
    {
        try(DatagramSocket server = new DatagramSocket(9999))
        {
            while(true)
            {
                int length = 1024;
                byte[] buf = new byte[length];
                DatagramPacket packet = new DatagramPacket(buf, length);
                
                server.receive(packet);
                
                System.out.println("receive from client.");
                
                buf = packet.getData();
                
                System.out.println(new String(buf, packet.getOffset(), packet.getLength()));

                packet.setData("server replly".getBytes());
                server.send(packet);
            }
        }
    }
}

[/codesyntax] 以下是客户端代码(理论上udp是没有客户端和服务端之分的,从下面的代码就可以看出来,客户端和服务端没什么区别): [codesyntax lang="java"]

/**
 * http://surenpi.com
 */
package org.suren.test;

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

/**
 * @author suren
 * @date 2015年9月2日 上午9:51:40
 */
public class UdpClient
{
    public static void main(String[] args) throws IOException
    {
        try(DatagramSocket client = new DatagramSocket())
        {
            byte[] buf = "hello from udp client message.".getBytes();
            int length = buf.length;
            DatagramPacket packet = new DatagramPacket(buf, length);
            packet.setSocketAddress(new InetSocketAddress("localhost", 9999));
            
            client.send(packet);
            
            client.receive(packet);
            
            System.out.println(new String(packet.getData(), packet.getOffset(), packet.getLength()));
        }
    }
}

[/codesyntax]

  • 安全的TCP

上面介绍的TCP连接,发送的都是明文的数据,通过数据包拦截工具就可以完全看到发送和接收的内容。当然,我们可以通过把要发送的数据先做加密,然后再发送。这就需要自己来编写加密和解密的逻辑了,安全性完全在于你的加密算法。另外,我们还可以使用SSL的TCP连接来发送明文或者密文数据,这是一种可以和普通TCP连接无缝对接的方式——和上面的写法几乎完全一样,只是在获取Socket的方式上有所区别。 既然是一种安全的通讯方式,肯定少不了相应的机制了。我们这里需要 使用keytool工具来生成一个证书文件,下面的代码中会用到。 下面是服务端代码: [codesyntax lang="java"]

/**
 * http://surenpi.com
 */
package org.suren.test;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

/**
 * @author suren
 * @date 2015年9月2日 上午10:11:54
 */
public class SSLTcpServer
{

    /**
     * @param args
     * @throws KeyStoreException 
     * @throws IOException 
     * @throws CertificateException 
     * @throws NoSuchAlgorithmException 
     * @throws UnrecoverableKeyException 
     * @throws KeyManagementException 
     */
    public static void main(String[] args) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, UnrecoverableKeyException, KeyManagementException
    {
        //证书加载
        char[] pwd = "123456".toCharArray();
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        
        try(InputStream input = new FileInputStream(new File("D:/suren")))
        {
            keyStore.load(input, pwd);
        }
        
        KeyManagerFactory keyMgr = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyMgr.init(keyStore, pwd);
        
        //初始化ssl上下文
        X509TrustManager x509m = new X509TrustManager(){

            @Override
            public void checkClientTrusted(X509Certificate[] chain,
                    String authType) throws CertificateException
            {
                System.out.println("checkClientTrusted");
            }

            @Override
            public void checkServerTrusted(X509Certificate[] chain,
                    String authType) throws CertificateException
            {
                System.out.println("checkServerTrusted");
            }

            @Override
            public X509Certificate[] getAcceptedIssuers()
            {
                System.out.println("getAcceptedIssuers");
                return null;
            }
        };
        
        SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(keyMgr.getKeyManagers(),
                new TrustManager[]{x509m},
                new SecureRandom());
        
        SSLServerSocketFactory factory = sslContext.getServerSocketFactory();
        
        try(SSLServerSocket server = (SSLServerSocket) factory.createServerSocket(8900))
        {
            System.out.println("ssl server socket created.");
            
            while(true)
            {
                try(Socket client = server.accept())
                {
                    InputStream input = client.getInputStream();
                    OutputStream output = client.getOutputStream();
                    
                    StringBuffer strBuf = new StringBuffer();
                    
                    int length = 1024;
                    byte[] buf = new byte[length];            
                    
                    while((length = input.read(buf)) > 0)
                    {
                        strBuf.append(new String(buf, 0, length));
                        
                        if(length < buf.length)
                        {
                            break;
                        }
                    }
                    
                    System.out.println(strBuf.toString());
                    
                    output.write("ssl server say done.".getBytes());
                }
            }
        }
    }
}

[/codesyntax] 下面是客户端代码: [codesyntax lang="java"]

/**
 * http://surenpi.com
 */
package org.suren.test;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

/**
 * @author suren
 * @date 2015年9月2日 上午10:52:31
 */
public class SSLTcpClient
{

    /**
     * @param args
     * @throws IOException 
     * @throws UnknownHostException 
     * @throws NoSuchAlgorithmException 
     * @throws KeyManagementException 
     * @throws KeyStoreException 
     * @throws CertificateException 
     * @throws UnrecoverableKeyException 
     */
    public static void main(String[] args) throws UnknownHostException, IOException, NoSuchAlgorithmException, KeyManagementException, KeyStoreException, CertificateException, UnrecoverableKeyException
    {
        SSLContext context = SSLContext.getInstance("SSL");
        context.init(null,
                new TrustManager[]{new X509TrustManager(){

                    @Override
                    public void checkClientTrusted(X509Certificate[] chain,
                            String authType) throws CertificateException
                    {
                    }

                    @Override
                    public void checkServerTrusted(X509Certificate[] chain,
                            String authType) throws CertificateException
                    {
                    }

                    @Override
                    public X509Certificate[] getAcceptedIssuers()
                    {
                        return null;
                    }
                }},
                new SecureRandom());
        
        SSLSocketFactory factory = context.getSocketFactory();
        
        try(SSLSocket client = (SSLSocket) factory.createSocket("localhost", 8900))
        {
            InputStream input = client.getInputStream();
            OutputStream output = client.getOutputStream();
            
            output.write("from ssl client.".getBytes());
            
            StringBuffer strBuf = new StringBuffer();
            byte[] buf = new byte[1024];
            int len = -1;
            while((len = input.read(buf)) > 0)
            {
                strBuf.append(new String(buf, 0, len));
                
                if(len < buf.length)
                {
                    break;
                }
            }
            
            System.out.println(strBuf);
        }
    }
}

[/codesyntax]

  • 参考

http://410063005.iteye.com/blog/1751243 http://www.ibm.com/developerworks/cn/java/j-lo-ssltls/

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Stella981 Stella981
3年前
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解2016年09月02日00:00:36 \牧野(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fme.csdn.net%2Fdcrmg) 阅读数:59593
Wesley13 Wesley13
3年前
Java日期时间API系列31
  时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到。Java中本来已经有相关获取时间戳的方法,Java8后增加新的类Instant等专用于处理时间戳问题。 1获取时间戳的方法和性能对比1.1获取时间戳方法Java8以前
Wesley13 Wesley13
3年前
P2P技术揭秘.P2P网络技术原理与典型系统开发
Modular.Java(2009.06)\.Craig.Walls.文字版.pdf:http://www.t00y.com/file/59501950(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fwww.t00y.com%2Ffile%2F59501950)\More.E
Wesley13 Wesley13
3年前
Java Socket
1\.套接字介绍套接字是介于传输层(TCP/UDP)和应用层(HTTP/FTP)之间的一个抽象,被应用程序调用;在java环境中套接字编程主要使用TCP/IP协议,但是套接字支持的协议族远不止这些;在java套接字编程中有Socket和ServerSocket两个核心类,ServerSocket位于服务器端监听连接,S
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Docker 部署SpringBoot项目不香吗?
  公众号改版后文章乱序推荐,希望你可以点击上方“Java进阶架构师”,点击右上角,将我们设为★“星标”!这样才不会错过每日进阶架构文章呀。  !(http://dingyue.ws.126.net/2020/0920/b00fbfc7j00qgy5xy002kd200qo00hsg00it00cj.jpg)  2
Wesley13 Wesley13
3年前
C语言、嵌入式应用:TCP通信实例分析
点击上方「嵌入式大杂烩」,选择「置顶公众号」第一时间查看嵌入式笔记!前言关于socket的笔记,之前已经有分享过两篇相关的文章:【socket笔记】TCP、UDP通信总结(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fmp.weixin.qq.com%2Fs