这段时间一直都在学习通信方面的知识,之前在文件压缩的学习中就已经接触到了字节的读取与写入,当时对于我而言还没有深入的理解。但这段时间的学习一直都在接触这方面的知识。这段时间的通信的学习过程中感悟最深的就是服务器与客户端传输三个方面功能的实现:服务器与客户端之间文本信息的传输;服务器与客户端之间图形的传输;服务器与客户端之间文件的传输。其实它们的本质是一样的都是字节的读取与写入。
一、发送文本信息就是将要发送的信息先放入到一个流中,即写入到输出流中,再进行接收就是将发送过来的信息从流中取出。部分代码如下:
/**
* 发送信息的方法
* @param str:要发送的信息
*/
public static void sendMsg(String str){
try{
fos.write((str+"\r\n").getBytes("utf-8"));
fos.flush();
}catch(Exception ef){
ef.printStackTrace();
}
}
/**
* 接收信息的方法
* @param fis:文件输入流
* @return:所要接收的信息
*/
public static String recieve(){
String str="";
try{
StringBuffer recieve=new StringBuffer();
int in=fis.read();
while(in!=13){
recieve.append((char)in);
in=fis.read();
}
str=new String((recieve.toString().trim()).getBytes("iso-8859-1"),"utf-8");
}catch(Exception ef){
ef.printStackTrace();
}
return str;
}
二、发送图形就是将图形的各个坐标进行写入和读取,将InputStream与OutputStream分别封装成DataInputStream、DataOutputStream基本数据输入输出流。然后各个坐标值由基本数据数据输入输出流进行写入与读出。在发送图形之前先要给发送各个图形各自的标识即先在输出流中写入标识,再在接收时读取出标识,接收时进行条件。(这里所说的也就是发送内容要用到的协议——协议可以自己定义,也可以参照其他已公开的协议。
部分代码如下:
/**
* 发送图形的方法
* @param x1
* @param y1
* @param x2
* @param y2
*/
public static void sendGraph(int x1,int y1,int x2,int y2){
try{
//从输出流写入一个字节——作为直线的标识
dos.write(1);
//写入各个坐标值
dos.writeInt(x1);
dos.writeInt(y1);
dos.writeInt(x2);
dos.writeInt(y2);
dos.flush();
}catch(Exception ef){
ef.printStackTrace();
}
}
/**
* 接收信息的方法
* @param fis:文件输入流
* @return:所要接收的信息
*/
public static String recieve(){
String str="";
try{
StringBuffer recieve=new StringBuffer();
int in=dis.read();
while(in!=13){
//设置条件,若读取到的为1,即直线的标识,则进行再读取(几个坐标值)
if(in==1){
int x1=dis.readInt();
int y1=dis.readInt();
int x2=dis.readInt();
int y2=dis.readInt();
//在服务器界面上接收到(即画出来)
Server.g.drawLine(x1,y1,x2,y2);
}
recieve.append((char)in);
in=dis.read();
}
str=new String((recieve.toString().trim()).getBytes("iso-8859-1"),"utf-8");
}catch(Exception ef){
ef.printStackTrace();
}
return str;
}
三、发送文件最主要的一点就是怎么写入就怎么读取,你想要发送文件的什么内容就将什么进行写入再按照写入的顺序格式进行读取。一般思路为:先将要发送的文件用文件输入流读取出来——>将读取出来的字节写入到输出中——>在另一端接收的方法中用输入流读取出来——>将读取出来的内容用文件输出流写入到另一文件中(即传送过去的文件中)。一般在写入时要写入文件的名字从而在传输过去后读取出文件的名字,使两者的名字保持一致(当然也可以不写入,将传输过去的文件重新命名——但这样比较麻烦也容易混淆)。在发送文件时最好在最开始也写入一个标识,用于在接收时进行条件的判断,也就是通信协议的制定。代码如下:
/**
* 发送文件的方法
* @param name:文件名字
* @param path:文件路径
*/
public static void sendFile(String name,String path){
try{
//从输出流写入一个字节——作为发送文件的标识
dos.write(2);
filein=new java.io.FileInputStream(path);
dis=new DataInputStream(filein);
//将要读的文件读出,放到(写入到)输出流中
//读取文件
int length=dis.available();
byte[] byt=new byte[length];
System.out.println("开始");
dis.read(byt);
//写入文件名字
dos.writeUTF(name);
//写入文件长度大小
dos.write(length);
//写入文件内容
dos.write(byt);
dos.flush();
}catch(Exception ef){
ef.printStackTrace();
}
}
/**
* 接收信息的方法
* @param fis:文件输入流
* @return:所要接收的信息
*/
public static String recieve(){
String str="";
try{
StringBuffer recieve=new StringBuffer();
int in=dis.read();
while(in!=13){
//设置条件,若读取到的为1,即直线的标识,则进行再读取(几个坐标值)
if(in==1){
int x1=dis.readInt();
int y1=dis.readInt();
int x2=dis.readInt();
int y2=dis.readInt();
//在服务器界面上接收到(即画出来)
Server.g.drawLine(x1,y1,x2,y2);
}
//设置条件发送的为文件
else if(in==2){
//将输出流中的读出,再写入到指定路径的文件中
String name=dis.readUTF();
//读取长度
int length=dis.read();
java.io.FileOutputStream fileout=new java.io.FileOutputStream("C:\\Users\\siqintana\\Desktop\\"+name);
dos=new DataOutputStream(fileout);
byte[] byt=new byte[length];
//将内容读取出来
dis.read(byt);
//再写入新的文件中
dos.write(byt);
System.out.println("结束");
}
recieve.append((char)in);
in=dis.read();
}
str=new String((recieve.toString().trim()).getBytes("iso-8859-1"),"utf-8");
}catch(Exception ef){
ef.printStackTrace();
}
return str;
}
由于自己比较懒几乎没怎么敲代码,还有很多功能还没有实现,有时间希望能实现更多的功能。。。