Java之Socket

  • 介绍
网络编程是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/

转载于:https://my.oschina.net/surenpi/blog/816920

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值