今天看了一点TCP协议,学会了通过TCP协议来进行简单的数据传输,以下是示例代码:
1.客户端
要实现数据传输,首先要建立一个Socket对象,它需要两个参数,要连接的服务器地址和端口.然后获取Socket的输入输出流对象,直接对它们进行读写操作即可.值得注意的是要等用户结束写之后才能关闭Socket,所以需要等待WriteThread结束才进行后续操作.而且很显然发送消息和接受消息是不同步的,因此要用到多线程.
import java.net.*;
import java.io.*;
public class TCPClient {
public static void main(String[] args) throws IOException{
String[] pref={"127.0.0.1","8889"};
String server = pref[0];
int servPort = Integer.parseInt(pref[1]);
//建立socket
Socket socket;
try{
socket=new Socket(server,servPort);
}catch (IOException ie){
System.out.println("Server shut down!");
return;
}
System.out.println("Server is connected!");
//获取输入输出流
InputStream in=socket.getInputStream();
OutputStream out=socket.getOutputStream();
//获取服务器传入数据
ReadThread show =new ReadThread(in);
show.start();
//通过out发送数据
WriteThread writer=new WriteThread(out);
writer.start();
//等待用户结束输入关闭
try {
writer.join();
}catch (InterruptedException ie){
ie.printStackTrace();
}
System.out.println("Conversation End!");
show.stop();
socket.close();
}
}
2.服务器
服务器要接受数据,需要始终运行.服务器对象为ServerSocket,构造它只需要一个参数,端口,因为它不需要主动连接客户端.我们需要通过它的accept()方法获得连接到它的客户端实例.再通过客户端的输入输出流对象操作数据的读写即可,这和上面操作客户端是一样的.
import java.net.*;
import java.io.*;
public class TCPServer {
public static void main(String[] args) throws IOException{
//建立服务端socket*/
System.out.println("Server is running...");
int serverPort = 8889;
ServerSocket serverSocket= new ServerSocket(serverPort);
while(true){
//获取客户端实例
Socket clientSocket =serverSocket.accept();
SocketAddress clientAddress = clientSocket.getRemoteSocketAddress();
System.out.println("\nConnect to "+clientAddress);
//获取输入输出流对象
InputStream in = clientSocket.getInputStream();
OutputStream out= clientSocket.getOutputStream();
//获取客户端传入数据并显示
ReadThread show=new ReadThread(in);
show.start();
//发送数据给客户端
WriteThread writer=new WriteThread(out);
writer.start();
//等待用户结束输入关闭
try {
writer.join();
}catch (InterruptedException ie){
ie.printStackTrace();
}
System.out.println("Conversation End!");
show.stop();
clientSocket.close();
}
}
}
3.接受数据线程
这个类实现了循环读取InputStream对象里的数据,并将其输出.要注意的是输入流对象的read(byte[] data)方法不会清空data的内容,只是简单的覆盖,因此需要手动清空data.import java.io.IOException;
import java.io.InputStream;
public class ReadThread extends Thread {
private InputStream in;
private byte[] data;
ReadThread(InputStream in){
this.in=in;
this.data=new byte[256];
}
@Override
public void run() {
try {
while (true){
if(in.read(data)!=-1){
System.out.println("Received:"+new String(data));
java.util.Arrays.fill(data, (byte) 0);
}
}
}catch (IOException ie){
ie.printStackTrace();
}
}
}
4.发送数据线程
这个类实现了通过OutputStream对象循环发送用户输入的数据,只至输入内容为close.
import java.io.IOException;
import java.io.OutputStream;
import java.util.Scanner;
public class WriteThread extends Thread{
private OutputStream out;
WriteThread(OutputStream out){
this.out=out;
}
@Override
public void run() {
Scanner input= new Scanner(System.in);
input.useDelimiter("\n");
String msg=input.nextLine();
while (!msg.equals("close")){
try{
out.write(msg.getBytes());
}catch (IOException ie){
ie.printStackTrace();
}
msg=input.nextLine();
}
}
}