java和C#之间SOCKET通信的问题
一、服务器端(使用java编写)
/** * 监听客户端的请求 * */ private static void socketService() { ExecutorService exec = Executors.newCachedThreadPool(); try { ServerSocket server=new ServerSocket(5678); int i = 1; while(true) { MyLogManager.InfoLog(log, null,"等待连接第"+i+"个用户..."); try { Socket client=server.accept(); MyLogManager.InfoLog(log, null,"第"+i+"个用户连接完成!"); exec.execute(new PDAServerWithDB(client)); } catch(Exception whileExp) { String msg = "多线程处理连接失败!"; MyLogManager.ErrorLog(log, whileExp, msg); } i++; } } catch(IOException ioe) { String msg = "连接失败!"; MyLogManager.ErrorLog(log, ioe, msg); exec.shutdown(); } }
具体对于Socket信息的接受和发送在PDAServerWithDB类中处理
信息处理分为:接收数据和发送数据
服务端接收数据一律采用ReadLine()方法,这要求客户端在发送请求时要有行结束符。
服务器的接收发送数据的代码
a)构造输入输出流
InputStream inPut = s.getInputStream(); OutputStream outPut = s.getOutputStream(); PrintWriter outWriter=new PrintWriter(outPut); BufferedReader inputReader =new BufferedReader(new InputStreamReader(inPut));
b)接收客户端请求的代码
String request = inputReader.readLine(); request = request.trim(); request = request.replaceAll(" ", "");
c)向客户端发送文本数据的代码
outWriter.println(strInfo); outWriter.flush();
d)向客户端发送文件的代码
// 发送文件长度 File file = new File(filePath); byte[] outBytes = new byte[1024]; int count = 0; FileInputStream fileInput = new FileInputStream(file); ByteArrayOutputStream ow = new ByteArrayOutputStream(); while ((count = fileInput.read(outBytes)) > 0) { MyLogManager.DebugLog(log, null, String.valueOf(count)); ow.write(outBytes, 0, count); } outPut.write(ow.toByteArray()); //outWriter.print(ow);//这个在JAVA客户端时可以正常响应,而在C#客户端中无法响应。 //outWriter.flush();
二、客户端(使用java和c#两个版本)
1).发送请求信息(字符串格式)
对于JAVA来说:直接使用PrintWrite类的println()方法即可。
而对于C#来说:需要使用socket.Send(System.Text.Encoding.ASCII.GetBytes(msg + ""));需要在请求信息msg后面加上一个行结束标志符。
2).接收数据(文本或者文件)
2-1).java客户端接收数据
a)java接收文本的代码示例:
******代码示例***** log.info("开始连接服务器"); InetAddress address = InetAddress.getByName(AppConfig.IP);//193.100.100.143); SocketChannel sc = SocketChannel.open(new InetSocketAddress(address,AppConfig.PORT)); log.info("服务器连接成功"); //连接成功 初始化流 InputStream inputStream = Channels.newInputStream(sc); InputStreamReader is = new InputStreamReader(inputStream,"GBK"); in = new BufferedReader(is); log.info("接收服务器的数据"); String responseLine=""; while ((responseLine = in.readLine()) != null) { //用readLine接收数据是,会自动抛弃换行符,如果为了保持数据的格式,需要在这里加上一个换行标识符 returnStr += responseLine+" "; } log.info("接收服务器的数据完毕"); **************
b)java接收文件的示例代码:
*****代码示例***** log.info("开始连接服务器"); InetAddress address = InetAddress.getByName("193.100.100.159");//193.100.100.143); SocketChannel sc = SocketChannel.open(new InetSocketAddress(address,AppConfig.PORT)); log.info("服务器连接成功,开始初始化流"); //连接成功 初始化流 OutputStream outputStream = Channels.newOutputStream(sc); InputStream inputStream = Channels.newInputStream(sc); InputStreamReader inputStreamReader = new InputStreamReader(inputStream); byte[] b = new byte[1024]; ByteArrayOutputStream bArrStream = new ByteArrayOutputStream(fileLength); int readCount = 0; while ((readCount = inputStream.read(b)) != -1) { log.info(readCount); bArrStream.write(b, 0, readCount); } log.info("size:"+bArrStream.toByteArray().length); log.info("接收服务器的数据完毕"); **************
2-2.) c#客户端接收数据的代码
a)接收文本数据
*****代码示例***** Socket socket = null; MemoryStream memStream = null; string returnMsg = string.Empty; //与服务器建立连接 socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPAddress add = IPAddress.Parse(appConfig.Ip); IPEndPoint endPt = new IPEndPoint(add, appConfig.Port); socket.Connect(endPt); //接收数据 byte[] buffer = new byte[1024]; int recCount = 0; memStream = new MemoryStream(); //接收返回的字节流 while ((recCount = socket.Receive(buffer)) > 0) { memStream.Write(buffer, 0, recCount); } Encoding encoding = Encoding.GetEncoding("GBK"); returnMsg = encoding.GetString(memStream.GetBuffer(), 0, memStream.GetBuffer().Length); **************
b)接收文件数据
****代码示例**** //接收数据 byte[] buffer = new byte[1024]; int recCount = 0; MemoryStream memStream = new MemoryStream(); while ((recCount = socket.Receive(buffer)) > 0) { memStream.Write(buffer, 0, recCount); } //接下来按照文件格式,将memStream保存为文件即可 **************
=======以上是终使用的代码版本===========
在开发过程中出现的问题及其解决
1.)文本乱码问题
java服务器端代码文件是使用GBK编码。所以在客户端读取的时候使用GBK编码进行转换。
2.)客户端和服务端的交互。
在服务端使用PrintWriter类来封装数据发送流(发送数据),new BufferedReader(new InputStreamReader(InputStream))来封装输入流(读取数据)
服务端读数据的时候是使用ReadLine方法,所以要求客户端发送请求时需要有一个行结束标志。对于java来说是用println()即可,
而对于C#则需要在发送信息的后面手动增加一个行结束标识符""。
对于服务端的反馈信息有两种反馈方式,一个是println(),一个是write(byte[])。前者是文本的发送,后者是文件的发送。
在使用print(object)方法对文件发送时,java客户端可是正确的接收数据,而C#客户端却不能,所以才采用了write(byte[])方法进行发送。
接收数据时,还要对按行发送的文本数据进行去尾处理
这个处理java和c#一样,只是方法名的大小写不同
str = str.trim(); str = str.replaceAll("", ""); str = str.replaceAll(" ", "");