欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java

程序员文章站 2022-06-29 23:44:14
...
通信阶段总结
学习通信有两点是我们需要学习的,一个是客户端与服务器的连接,一个是协议的制定。
对于客户端与服务器的连接,其实掌握几行代码就能轻松解决:
首先我们先建立一个客户端:
  Socket client = new Socket(IP,port);
这样就建立了一个客户端,在这里只要传入一个连接时需要使用的IP地址和端口号就OK了。建立服务器并且实现与客户端的连接。
  ServerSocket server = new ServerSocket(port);
在指定的端口创建服务器,然后就可以等待客户端的连接。
  Socket client = server.accept();
通信主要是进行信息的发送,接收和发送信息主要是通过流来实现的,最重要的是,我们发送信息使用的流一定要和接收信息使用的流一致,这样才能保证数据的传送正确。
一:文本的发送:信息发送一般发送的是字节,当然也可以发送int数值或者是一个缓冲的字节数组。
代码如下:
//client作为一个管道进行输入输出流的通道
in = client.getInputStream();
dis = new DataInputStream(in);
out = client.getOutputStream();
有了管道我们就可以发送消息了,消息不论是从客户端向服务器发送还是从服务器向客户端发送,所用的方法一样

//向服务器发送消息
out.write(("Client:"+str+"\r\n").getBytes());
ClientUI.ja1.append(str+"\r\n");
out.flush();
System.out.println("客户端已发送信息");

因为发送是以字节发送的,所以接收的时候我们也要使用相同的方法

int i=in.read();
StringBuffer sb = new StringBuffer();
//回车键的时候终止循环
while(i!=13){
sb.append((char)i);
i = in.read();
}
fromServer = sb.toString().trim();
System.out.println("fromServer="+fromServer);
//显示在构造的面板上
ClientUI.ja1.append(fromServer+"\r\n");

二:以画板的形式传送图片
所谓传送图片我们传送的仍然是字节或者int型的数值,下面是以传送直线为例的,两点确定一条直线,所以我们只要传送四个数值就可以了。

//发送坐标的方法
public static void sendPoint() {

try{
// 利用DataOutputStram没有OutputStream只发送0-255之间的限制
DataOutputStream dos = new DataOutputStream(out);
out.write(2);
//获取监听器中获得的坐标,然后发送出去
dos.writeInt(ClientDrawListener.x1);
dos.writeInt(ClientDrawListener.y1);
dos.writeInt(ClientDrawListener.x2);
dos.writeInt(ClientDrawListener.y2);

}catch(Exception e){
e.printStackTrace();
}
}
//利用与DataOutputStream对应的DisInputStream流
int x1 = dis.readInt(); //获取读到的x1坐标
int y1 = dis.readInt(); //获取读到的y1坐标
int x2 = dis.readInt();
int y2 = dis.readInt();
System.out.println("client接收到:");
System.out.println("=========="+x1+" "+y1+" "+x2 +" "+y2);
//获取到坐标以后便在面板上画出相应的图形
ClientUI.gc.drawLine(x1, y1, x2, y2);

三:传送文件
传送文件其实和传送文本一致,首先我们要在发送文件的按钮上添加监听器。

JButton jb3 = new JButton("发送文件");
//给发送文件按钮添加监听器
jb3.addActionListener(new ActionListener(){
public void actionPerformed (ActionEvent e) {
JFileChooser jf = new JFileChooser();
//在ClientUI上显示文件选择器
jf.showOpenDialog(ClientUI.this);
//文件选择模式
jf.setFileSelectionMode (JFileChooser.FILES_AND_DIRECTORIES);

//获得选择的文件
chFile = jf.getSelectedFile();
//获得选择的文件的路径
frompath = chFile.getAbsolutePath();
//获得文件名
fileName = chFile.getName();
try {
Client.sendFile();
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
this.add(jb3);


在文件选择器中选取文件后,我们已经获取了文件名和文件大小,下面我们直接就可以进行发送了

/**
* 发送文件
* @throws IOException
*/
public static void sendFile() throws IOException{
//输出流
DataOutputStream dos = new DataOutputStream(out);
//首先要写出发送的类型
out.write(3);
//写出文件大小
dos.writeInt((int) ClientUI.chFile.length());
//要写出文件名
dos.writeUTF(ClientUI.fileName);

//创建一个专门读取文件的流
FileInputStream fis = new FileInputStream(ClientUI.chFile);
//封装在data流中f
DataInputStream disf = new DataInputStream(fis);
//获取文件的大小以便于写出文件
for(int i=0;i<ClientUI.chFile.length();i++){
//从文件中读取字节
byte fromfile = disf.readByte();
System.out.println("从文件中获取的字节:"+fromfile+" "+(char)fromfile);
//然后写出文件到管道中去
dos.writeByte(fromfile);
}
}

最后,我们把文件用相同的流去接收就OK啦。


//管道输入流
DataInputStream dis = new DataInputStream(in);
String path = "D:\\aa.txt";
//输入到新的文件的输入流
File tof = new File(path);
FileOutputStream fos = new FileOutputStream(tof);
DataOutputStream dosf = new DataOutputStream(fos);
//接收文件的大小
int flength = dis.readInt();
System.out.println("文件大小为:"+flength);
//要接收文件名
String fileName = dis.readUTF();
System.out.println("文件名为:"+fileName);
//将接收到的文件名写入到新的文件中去
dosf.writeUTF(fileName);

StringBuffer sb = new StringBuffer();
//接收文件内容,要接收字节
String str = null;
for(int i = 0;i<flength;i++){
byte bf = dis.readByte();
System.out.println("收到的字节:"+(char)bf);
str = sb.append((char)bf).toString().trim();
System.out.println("转化为字符串为:"+str);
dosf.writeChar((char)bf);

}
相关标签: 通信