1、tcp通信
例程:由客户端发一条字符串到服务端,服务端收到之后相应,客户端收取相应字符串。
首先是服务端接受连接的代码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class Test {
public static void main(String[] args) throws IOException, InterruptedException {
//创建一个服务端socket,指定绑定端口
ServerSocket serverSocket = new ServerSocket(8888);
//开始监听端口,等待客户端的连接
System.out.println("服务器已经启动,进入阻塞状态,等待客户端连接");
Socket socket = serverSocket.accept();
System.out.println("收到客户端连接,客户端ip为:"+socket.getRemoteSocketAddress());
//获取一个输入流,读取信息
InputStream is = socket.getInputStream();//字节输入流
InputStreamReader reader = new InputStreamReader(is);//将字节输入流转换为字符流,如果要接收对象,就改成ObjectInputStream
BufferedReader br = new BufferedReader(reader);//为字符流添加缓冲
String receive = null;
while((receive=br.readLine())!=null){
System.out.println("收到客户端信息:"+receive);
}
socket.shutdownInput();//关闭输入流
//获取输出流,相应客户端的请求
Thread.sleep(5000);//延迟响应
OutputStream os = socket.getOutputStream();
PrintWriter out = new PrintWriter(os);//如果要发哦是哪个对象,就把这里改为ObjectOutputStream
out.write("欢迎你客户端!");
out.flush();//本句必须执行
//关闭资源
out.close();
br.close();
reader.close();
is.close();
socket.close();
serverSocket.close();
}
}
然后是客户端发送请求连接的代码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class TestClient {
public static void main(String[] args) throws UnknownHostException, IOException {
// TODO Auto-generated method stub
//1、创建一个socket,指定服务器地址和端口号
System.out.println("正在试图向服务器端建立连接");
Socket socket = new Socket("192.168.1.147",8888);
System.out.println("连接建立成功,准备发送消息");
//2、获取输出流向服务端发送信息
OutputStream outputStream = socket.getOutputStream();
PrintWriter printWriter = new PrintWriter(outputStream);//将输出流包装成打印流,如果要传输对象,就把这里改为ObjectOutputStream
printWriter.print("服务器你好");//可以调用ObjectOutputStream的writeObject方法
printWriter.flush();//本句必须执行
System.out.println("信息发送成功!!等待服务器相应");
//关闭输出流
socket.shutdownOutput();
//3、获取输入流,接收服务器的相应
System.out.println("服务器正在响应,服务器ip"+socket.getRemoteSocketAddress());
InputStream is = socket.getInputStream();
InputStreamReader reader = new InputStreamReader(is);
BufferedReader buffer = new BufferedReader(reader);//包装为字符流
String response = null;
while((response = buffer.readLine())!=null){
System.out.println("收到服务器响应内容:"+response);
}
//关闭相关资源
buffer.close();
is.close();
printWriter.close();
socket.close();
}
}
在上例中服务器一次只能接收一个客户端发来的请求,并且响应完毕后程序即结束,如果要使服务器可以相应多个客户端的请求,就需要用到子线程,下面把服务端的代码挪到一个子线程中去
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
public class ServerThread extends Thread {
public Socket socket;
public ServerThread(){}
public ServerThread(Socket socket){
this.socket = socket;
}
public void run(){
//获取一个输入流,读取信息
InputStream is = null;//字节输入流
InputStreamReader reader = null;//将字节输入流转换为字符流
BufferedReader br = null;
PrintWriter out = null;
try {
is = socket.getInputStream();//字节输入流
reader = new InputStreamReader(is);//将字节输入流转换为字符流
br = new BufferedReader(reader);//为字符流添加缓冲
String receive = null;
while((receive=br.readLine())!=null){
System.out.println("收到客户端信息:"+receive);
}
socket.shutdownInput();//关闭输入流
//获取输出流,相应客户端的请求
Thread.sleep(5000);//延迟相应
OutputStream os = socket.getOutputStream();
out = new PrintWriter(os);
out.write("欢迎你客户端!");
out.flush();//本句必须执行
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
//关闭资源
try {
if(out!=null)out.close();
if(br!=null)br.close();
if(reader!=null)reader.close();
if(is!=null)is.close();
if(socket!=null)socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
调用方法:
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
ServerSocket serverSocket = new ServerSocket(8888);
int count=0;//记录客户端的数量
Socket socket=null;
System.out.println("服务器已经启动,进入阻塞状态,等待客户端连接");
//循环监听,等待客户端的连接
while(true){
socket = serverSocket.accept();//此处进行阻塞
//如果收到客户端请求,就创建一个新的线程
System.out.println("收到客户端连接,客户端ip为:"+socket.getInetAddress().getHostAddress());
ServerThread serverThread = new ServerThread(socket);
serverThread.setPriority(4);//设置线程优先级,防止服务器卡掉
//启动线程
serverThread.start();
count++;
}
}
2、UDP通信,与tcp相同,不过使用的socket类为DatagramSocket,而且发的不是字节流,而是报文
服务端例程
public static void main(String[] args) throws IOException, InterruptedException {
// TODO Auto-generated method stub
//创建服务器端DatagramSocket,指定端口
DatagramSocket socket = new DatagramSocket(8800);
//创建数据报,用于接收客户端发的数据
byte[] data = new byte[1024];
DatagramPacket clientPacket = new DatagramPacket(data, data.length);//接收用两个参数的构造,发送用四个
//3、接收客户端发送的数据,保存在数据报中
System.out.println("udp接收端已经启动,正在等待数据");
socket.receive(clientPacket);//此方法在接收到数据报之前会一直阻塞
//4、读取数据报,其实就是data字节数组
String info = new String(data,0,clientPacket.getLength());//第二个参数是偏移,第三个参数是长度
System.out.println("客户端发来:"+info);
/**
* 向客户端相应数据
*/
Thread.sleep(2000);
//1、定义客户端的地址、端口号、数据
InetAddress clientAddress = clientPacket.getAddress();//这里的packet就是socket收到的packet,里面全是客户机的信息
byte[] data2 = "欢迎udp客户端!!".getBytes();
//2、创建数据报,包含响应的数据信息
DatagramPacket serverPacket = new DatagramPacket(data2, data2.length, clientAddress,clientPacket.getPort());//发送数据报用4个参数的构造函数
//3、发送数据报
socket.send(serverPacket);//DatagramSocket只记录自己的端口和地址,对于要发出的,根据传入的packet来确定
}
客户端例程
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
//1、定义服务器的地址,端口号、数据
InetAddress inetAddress = InetAddress.getByName("192.168.1.147");//给出目标主机的InetAddress
int port = 8800;
byte[] data = "你好我是UDP请求".getBytes();
//2、创建数据报,包含发送的数据信息
DatagramPacket packet = new DatagramPacket(data, data.length, inetAddress, port);//发送数据用4个参数的构造函数
//3、创建datagramSocket对象
DatagramSocket socket = new DatagramSocket();
//4、发送数据报
socket.send(packet);
System.out.println("udp发送成功");
/**
* 接受服务端响应的数据
*/
//1、创建数据报
byte[] data2 = new byte[1024];
DatagramPacket serverPacket = new DatagramPacket(data2, data2.length);
//2、接收响应的数据
socket.receive(serverPacket);
//3、读取数据
String reply = new String(data2,0,serverPacket.getLength());
System.out.println("服务器响应内容:"+reply);
}
3、使用socket发送小文件文件
客户端例程
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class TestClient {
public static void main(String[] args) throws UnknownHostException, IOException {
// TODO Auto-generated method stub
//1、创建一个socket,指定服务器地址和端口号
System.out.println("正在试图向服务器端建立连接");
Socket socket = new Socket("192.168.1.147",8888);
System.out.println("连接建立成功,准备发送消息");
//2、获取输出流向服务端发送信息
OutputStream outputStream = socket.getOutputStream();
FileInputStream fileInputStream = new FileInputStream(new File("E:/xh.jpg"));
BufferedInputStream bis = new BufferedInputStream(fileInputStream);
byte[] bytes = new byte[fileInputStream.available()];//把整个文件都放到内存里去,注意文件不要过大
bis.read(bytes);
outputStream.write(bytes);
if(fileInputStream!=null){
fileInputStream.close();
}
//关闭输出流
socket.shutdownOutput();
//3、获取输入流,接收服务器的相应
System.out.println("服务器正在响应,服务器ip"+socket.getRemoteSocketAddress());
InputStream is = socket.getInputStream();
InputStreamReader reader = new InputStreamReader(is);
BufferedReader buffer = new BufferedReader(reader);//包装为字符流
String response = null;
while((response = buffer.readLine())!=null){
System.out.println("收到服务器响应内容:"+response);
}
//关闭相关资源
buffer.close();
is.close();
socket.close();
}
}
服务端例程
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class Test {
public static void main(String[] args) throws IOException, InterruptedException {
//创建一个服务端socket,指定绑定端口
ServerSocket serverSocket = new ServerSocket(8888);
//开始监听端口,等待客户端的连接
System.out.println("服务器已经启动,进入阻塞状态,等待客户端连接");
Socket socket = serverSocket.accept();
System.out.println("收到客户端连接,客户端ip为:"+socket.getRemoteSocketAddress());
//获取一个输入流,读取信息
InputStream is = socket.getInputStream();//字节输入流
BufferedInputStream clientInputStream = null;
//生成一个临时文件
File file = new File("e:/xh.jpg");
clientInputStream = new BufferedInputStream(socket.getInputStream());
file.createNewFile();
BufferedOutputStream fos = new BufferedOutputStream(new FileOutputStream(file));//对输出流进行缓存控制
byte[] buf = new byte[1024*256];//每次写入256k
int len;
while((len = clientInputStream.read(buf))!=-1){
fos.write(buf,0,len);
fos.flush();
System.out.println("写入字节流成功"+len);
}
socket.shutdownInput();//关闭输入流
//获取输出流,相应客户端的请求
OutputStream os = socket.getOutputStream();
PrintWriter out = new PrintWriter(os);//如果要发个对象,就把这里改为ObjectOutputStream
out.write("文件写入成功!");
out.flush();//本句必须执行
socket.shutdownOutput();
//关闭资源
out.close();
is.close();
socket.close();
serverSocket.close();
}
}