客户端用C发送文件到Java服务器

前言

在写客户端发送文件到Java服务器的时候,一是遇到了Netty接收默认字节长度的问题,Netty默认的接收长度是1024,这个问题通过DelimiterBasedFrameDecoder解决。二是我一开始除了应用DelimiterBasedFrameDecoder之外,还应用了StringDecoder,结果在Handler里(继承自ChannelHandlerAdapter),接收到的object是String,然后通过String.getBytes()获得的字节流的长度总是和原文件的长度不同(通过notepad++查看)。随后,我把StringDecoder去掉了,只用DelimiterBasedFrameDecoder就可以了。

其中C端,我用的Windows上的零拷贝函数TransmitFile(),因为是通过字节流写文件的,所以如果通过记事本打开的文件包含中文的话会出现乱码问题。

源程序

客户端(C):

VS2019,Debug,Win32

#include <stdio.h>
#include <stdlib.h>

#include <ws2tcpip.h>
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")

#include <MSWSock.h>
#pragma comment(lib, "Mswsock.lib ")

int sendFile()
{
	const wchar_t* fileName = L"D:/writeJson.txt";
	const char* ip = "127.0.0.1";
	const char* port = "8080";
	

	// 创建并初始化winsock数据变量
	WSADATA wsaData = { 0 };
	int iResult = 0;

	SOCKET hSocket = INVALID_SOCKET;
	int iFamily = AF_INET;
	int iType = SOCK_STREAM;
	int iProtocol = IPPROTO_TCP;

	// 初始化 Winsock
	iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
	if (iResult != 0) {
		printf("WSAStartup failed: %d\n", iResult);
		return -1;
	}
	// 打开socket
	hSocket = socket(iFamily, iType, iProtocol);
	if (hSocket == INVALID_SOCKET) {
		printf("socket function failed with error = %d\n", WSAGetLastError());
		WSACleanup();
		return -2;
	}

	// 设置远程段地址
	sockaddr_in remoteAddr;
	remoteAddr.sin_family = AF_INET;
	//remoteAddr.sin_addr.s_addr = inet_addr(v[2]);
	//绑定ip
	inet_pton(AF_INET, ip, &remoteAddr.sin_addr);
	//绑定端口
	remoteAddr.sin_port = htons(atoi(port));
	
	do {
		// 打开文件
		HANDLE hFile = CreateFile((LPCWSTR)fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
		if (hFile == INVALID_HANDLE_VALUE) {
			iResult = -3;
			printf("打开文件失败");
			break;
		}
		// 获取文件大小
		//GetFileSize(hFile, NULL);
		LARGE_INTEGER liFileSize;
		if (GetFileSizeEx(hFile, &liFileSize) == FALSE) {
			iResult = -4;
			printf("获取文件大小失败");
			break;
		}
		
		// 连接到远程端
		iResult = connect(hSocket, (SOCKADDR*)&remoteAddr, sizeof(remoteAddr));
		if (iResult == SOCKET_ERROR) {
			printf("connect function failed with error: %ld\n", WSAGetLastError());
			iResult = -5;
			break;
		}
		// 使用TransmitFile发送文件
		if (TransmitFile(hSocket, hFile, 0, 0, NULL, NULL, TF_USE_DEFAULT_WORKER) == FALSE) {
			printf("TransmitFile function failed with error: %ld\n", WSAGetLastError());
			iResult = -6;
			break;
		}
	} while (0);
	const char* endStr = "$_$";
	//发送结尾标识符
	iResult = send(hSocket, endStr, strlen(endStr) + 1, 0);
	if (iResult == SOCKET_ERROR) {
		printf("发送结尾标记失败\n");
		iResult = -10;
	}
	// 关闭socket
	iResult = closesocket(hSocket);
	if (iResult == SOCKET_ERROR) {
		printf("closesocket failed with error = %d\n", WSAGetLastError());
		iResult = -7;
	}
	// 清理
	WSACleanup();

	return iResult;
}

服务器端Netty接收(Java):

Netty版本:

监听端口程序HttpServer.java:

public class HttpServer {
    /**
     * 监听端口
     */
    private static int port = 8080;

    public static void main(String[] args) {
        HttpServer httpServer = new HttpServer();
        httpServer.acceptWait();
    }

    /**
     * @Description : Netty监听数据请求
     * @author : 申劭明
     * @date : 2019/9/17 10:29
     */
    public void acceptWait() {
        //监听请求
        EventLoopGroup listenGroup = new NioEventLoopGroup();
        //请求处理
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        ServerBootstrap bootstrap = new ServerBootstrap();
        //绑定监听请求和处理请求的group
        bootstrap.group(listenGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        socketChannel.pipeline()
                                //采取灵活的数据长度接收数据,入参为单位是字节,1<<4<<20表示16MB,发送信息以$_$结尾
                                .addLast(new DelimiterBasedFrameDecoder(1<<4<<20, Unpooled.copiedBuffer("$_$".getBytes())))
                                .addLast(new RequestHandler());
                    }
                });
        ChannelFuture future = null;
        try {
            future = bootstrap.bind(port).sync();
            future.channel().closeFuture().sync();

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            listenGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

自己定义的Handler,RequestHandler.java:

public class RequestHandler extends ChannelHandlerAdapter {

    public RequestHandler(){
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.err.println(msg.getClass());
        if (msg instanceof ByteBuf){
            ByteBuf byteBuf = (ByteBuf)msg;
            System.out.println(byteBuf.toString(CharsetUtil.US_ASCII).length());
            if (byteBuf.toString(CharsetUtil.US_ASCII).length() < 10){
                return;
            }

            File file = new File("D:/test.jpg");
            //DMA
            RandomAccessFile randomAccessFile = new RandomAccessFile(file,"rw");
            //从文件开头写数据
            randomAccessFile.seek(0);
            byte[] bytes = new byte[byteBuf.readableBytes()];
            byteBuf.readBytes(bytes);
            System.out.println(bytes.length);
            randomAccessFile.write(bytes);
            randomAccessFile.close();
            ctx.close();
        }else{
            return;
        }

    }

    //    @Override
//    protected void messageReceived(ChannelHandlerContext channelHandlerContext, Object o) {
//        //接收数据
//        Request request = new Request((ByteBuf) o);
//        String receiveMessage = request.getMessage();
//        System.out.println(receiveMessage);
//        if (receiveMessage.contains("\"wxid\":\"gh_")){
//            return;
//        }
//        String receiveMessage = ((ByteBuf)o).toString(CharsetUtil.US_ASCII);
//        System.err.println(receiveMessage);
//
//        channelHandlerContext.close();
//    }


    public static String httpGet(String message){
        HttpClient httpClient = null;
        try {
            URL url = new URL("http://192.168.100.100:9000/cardb/testWord?word=" + message);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoInput(true);
            connection.setRequestMethod("GET");
            BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), CharsetUtil.UTF_8));
            String line = null;
            StringBuilder result = new StringBuilder();
            while ((line = br.readLine()) != null){
                result.append(line);
            }
            connection.disconnect();
            System.err.println(result);
            JSONObject jsonObject = new JSONObject(result.toString());
            return jsonObject.get("data").toString();
        } catch (IOException e) {
            e.printStackTrace();
        } finally{
            if (httpClient != null){
                httpClient.closeServer();
            }
        }
        return null;
    }

    private static String httpGet(Message message){
        return httpGet(message.getContent());
    }
}
发布了74 篇原创文章 · 获赞 23 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/shenshaoming/article/details/103138148
今日推荐