要实现多台电脑的联通互动,就得用到通信。通信总体说起来就是服务器和客户端的数据传输。通信的过程大概是,先建立服务器,然后启动客户端连接到服务器,然后客户端将消息(数据)按协议发送给服务器,然后服务器根据相同的协议来解析消息并做出反应,或是传送给另一个客户端,或是传回原客户端,或是保存到服务器中。说起来是如此的简单,但是真正将两台电脑联通起来还是有各种各样的问题的,其中尤为重要的就是协议问题,协议必须一致,两个客户端才能实现信息的传输。在定协议的时候,读取数据的时候如果要将一个byte数组读满,最好不要使用read()方法,而是使用readFully()方法,因为使用read()方法很有可能读不满整个数组,而readFully()方法则很好的解决了这个问题。下面是最简陋的客户端与服务器之间的消息以及文件的数据传输代码:
//服务器 import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; public class ChatServer{ /** * @param args */ public static void main(String[] args) { ChatServer cs = new ChatServer(); cs.setUpSever(3335); } //建立端口port的服务器 public void setUpSever (int port) { ServerSocket server; try { server = new ServerSocket(port); System.out.println("服务器创建成功 "+port); while(true){ Socket client = server.accept(); ClientThread ct = new ClientThread(client); System.out.println(client.getRemoteSocketAddress()+"客户连接"); ct.start(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; public class ClientThread extends Thread{ private Socket client ; public ClientThread(Socket client){ this.client = client ; } public void run(){ try { processChat(client); } catch (IOException e) { e.printStackTrace(); } } //处理连接对象(聊天过程) public void processChat (Socket client) throws IOException{ OutputStream out = client.getOutputStream(); InputStream in = client.getInputStream(); DataInputStream din = new DataInputStream(in); String s= "欢迎来到服务器!\r\n"; byte[] dat = s.getBytes(); out.write(dat); out.flush();//强制输出 String inputs =null; while(true){ //消息长度 int totalLen = din.readInt(); //消息类型 byte flag = din.readByte(); //目标客户端编号 int destNum = din.readInt(); //根据消息类型来选择处理方式 System.out.println("len:"+totalLen+" flag: "+flag+"destNum:"+destNum); if(flag==1) {//文本消息 System.out.print("*"); byte [] data = new byte[totalLen]; din.readFully(data); String msg = new String (data,"GBK"); System.out.println("发送给"+destNum+":"+msg); } else if(flag==2){//文件消息 //文件名 byte [] data = new byte[256]; din.readFully(data); String fileName = new String(data,"GBK").trim();//去除空格 fileName="H:\\3.txt"; System.out.println(fileName); //文件内容 data = new byte [totalLen]; System.out.println(data.length); din.readFully(data); FileOutputStream fout = new FileOutputStream(fileName); fout.write(data); fout.flush(); fout.close(); } } } //按行读消息(含) private String readString(InputStream in) throws IOException{ //创建字符串缓冲区 ByteArrayOutputStream bos = new ByteArrayOutputStream(); StringBuffer stb = new StringBuffer(); int i=0; while(true){ i=in.read(); if(i=='\r') {continue;} if(i=='\n') {break;} bos.write(i); } byte [] bytes = bos.toByteArray(); String inputS = new String(bytes,"GBK"); System.out.println("******"+inputS+"***********"); return inputS; } } //客户端 package Client; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException; import java.util.Scanner; import javax.swing.JFrame; public class Client extends JFrame { /** * @param args */ private static DataOutputStream dout; public static void main(String[] args) { Client ct = new Client (); //client.setSize(new Dimension(300,400)); //client.setName("客户端"); //JButton jbt = new JButton ("发送"); String ip="localhost";int port=3335; try { Socket client = new Socket(ip,port); InputStream in = client.getInputStream(); OutputStream out = client.getOutputStream(); dout=new DataOutputStream(out); while(true){ System.out.println("请输入要发的文件类型:"); Scanner sc = new Scanner(System.in); int type = sc.nextInt(); if(type==1){ sendTextMsg("111111111",3333); } else if(type==2){ sendFileMsg("H:\\1.txt",3333); } } } catch (UnknownHostException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private static void sendTextMsg(String msg, int destNum) { byte[] strb = msg.getBytes(); int totallen = strb.length; try { dout.writeInt(totallen); System.out.println("totallen:"+totallen); dout.writeByte(1); dout.writeInt(destNum); dout.write(strb); dout.flush(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private static void sendFileMsg(String fileName,int destNum){ System.out.println(fileName); File file = new File(fileName); try { FileInputStream in = new FileInputStream(file); int datalen=in.available(); dout.writeInt(datalen); dout.writeByte(2); dout.writeInt(destNum); int i=0; byte [] fnstring = fileName.getBytes(); dout.write(fnstring); i=256-fnstring.length; for(int j=0;j<i;j++) dout.write('\0'); System.out.println(i); byte [] fileData = new byte[datalen]; in.read(fileData); dout.write(fileData); dout.flush(); in.close(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }