java在网络方面的出色表现相信大家有目共睹,用java做Socket编程是件有趣的事情,下面是实际项目中的代码,初学者可能觉得不是那么浅显易懂,所以加入了详细注释,废话不多说了服务端代码如下:
不知你有没有注意到,服务器端在读流时用的是读字节流的方式,而没有用到处理流,处理流经常会带来高效率,不过我们在处理二进制流的时候,尽量还是用最原始的方法,因为字符流在处理数据的时候,会将占两个字节的“00”转换后还剩下一个字节长度。
接下来是FTP请求端的代码:
有了服务端和请求端代码Socket的基本通信已经完成了,对,就是这么简单。接下来就是对自定义数据包的打包和解包工作了,首先包头定义如下:
待续//
- package com.tcp;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.net.ServerSocket;
- import java.net.Socket;
- public class TcpServer {
- public static void main(String[] args) throws IOException {
- // 声明用来计数的int局部变量
- int count = 0;
- byte[] head = new byte[29];
- byte[] body;
- try {
- // 使用ServerSocket
- ServerSocket server = new ServerSocket(9999);
- // 打印提示信息
- System.out.println("服务器端正在对端口9999进行监听");
- // 等待客户端连接
- while (true) {
- // 若有连接返回对应的Socket对象。
- Socket sc = server.accept();
- // 获取当前链接对象的输入流
- InputStream din = sc.getInputStream();
- // 获取当前连接对象的输出流
- OutputStream dout = sc.getOutputStream();
- // 读取包头并打印包头所包含的信息
- din.read(head);
- System.out.println("==========================" + (++count)
- + "========================");
- System.out.println("客户端IP地址:" + sc.getInetAddress());
- System.out.println("客户端端口号:" + sc.getPort());
- System.out.println("本地端口号:" + sc.getLocalPort());
- System.out
- .println("接收到的数据包16进制表示为:" + byteToHexStr(head, true));
- // 判断,如果是请求包则返回一个响应
- if (head[0] == 1) {
- //临时代码,接收请求包并原样返回消息包头
- head[0] = 2;
- dout.write(head);
- System.out.println("******收到请求包,已返回响应......******");
- } else if (head[0] == 2) {
- System.out.println("************收到响应包****************");
- } else {
- System.out.println("*******数据包已损坏,接收失败************");
- }
- // 关闭流
- din.close();
- dout.close();
- // 关闭Socket连接
- sc.close();
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- //该方法将数据转为16进制显示
- public static String byteToHexStr(byte[] bArray, boolean format) {
- StringBuffer strb = new StringBuffer(bArray.length);
- String str;
- for (int i = 0; i < bArray.length; i++) {
- str = Integer.toHexString(0xFF & bArray[i]).trim();
- if (str.length() < 2){
- str = "0" + str;
- }
- if (format){
- str += " ";
- }
- strb.append(str);
- }
- str = strb.toString().toUpperCase().trim();
- return str;
- }
- }
不知你有没有注意到,服务器端在读流时用的是读字节流的方式,而没有用到处理流,处理流经常会带来高效率,不过我们在处理二进制流的时候,尽量还是用最原始的方法,因为字符流在处理数据的时候,会将占两个字节的“00”转换后还剩下一个字节长度。
接下来是FTP请求端的代码:
- package com.tcp;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.net.Socket;
- public class TcpSend {
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- byte[] bt = new byte[29];
- try {
- // 创建连接到服务端的Socket对象
- Socket cs = new Socket("10.168.69.177", 9999);
- // 获取当前连接的输入流/输出流
- InputStream din = cs.getInputStream();
- OutputStream dout = cs.getOutputStream();
- // 模拟一个请求消息包.
- byte[] pack = new EncodePackage().gepPackage();
- //发送请求消息包.
- dout.write(pack);
- // 从服务器中读取数据并打印
- din.read(bt, 0, 29);
- if (bt[0] == 2) {
- System.out.println("=======收到响应包=======");
- System.out.println("包类型:" + bt[0]);
- System.out.println("包标识:" + new String(bt, 1, 4));
- System.out.println("包长度:" + new Integer(new String(bt, 5, 4)));
- System.out.println("MD5校验和:" + new String(bt, 9, 16));
- System.out.println("版本号:" + bt[25]);
- System.out.println("协议类型:" + (byte) (bt[26]));
- System.out.println("命令类型" + new String(bt, 27, 2));
- }
- // 关闭流,关闭Socket连接
- din.close();
- dout.close();
- cs.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
有了服务端和请求端代码Socket的基本通信已经完成了,对,就是这么简单。接下来就是对自定义数据包的打包和解包工作了,首先包头定义如下:
待续//