Socket 通讯入门


1、Socket套接字

  • 网络上的两个程序经过一个双向的通讯您链接实现数据交换,这个链接的一端称为一个socket。
  • java中使用socket完成TCP程序的开发,使用此类方法能够方便的创建可靠地,双向的,持续性的,点对点得通信链接
  • 在socket的程序开发中,服务器端使用ServerSocket等待客户端的链接,对于java的网络程序来讲,每个客户端都是用一个socket对象表示。

2、代码示例

2.1 完成一次服务端与客户端通讯

  • 用本机的当作服务器与客户端进行通讯。
  • 服务端等待客户端的链接,在客户端链接后发送数据给客户端。

Server

package com.rrs.socketserver;

import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

import org.junit.Test;

/**
 * @author lzx
 * on 2019/9/25.
 */
public class SocketServer {

	@Test
	public void test01() throws IOException {

		System.out.println("socket server start...");
		ServerSocket serverSocket = new ServerSocket(8888);

		Socket socket = serverSocket.accept();
		System.out.println("检测到客户端socket:" + socket);

		OutputStream out = socket.getOutputStream();

		String mString = "Hello Client";
		byte[] bytes = mString.getBytes();

		out.write(bytes);

		socket.shutdownOutput();
		out.close();

	}

}

Client

package com.rrs.sockerclient;

import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.SocketAddress;

/**
 * Created by lzx on 2019/9/25.
 */
public class SocketClient {


    public static void main(String[] args) throws IOException {

        System.out.println("socket client start...");
        Socket socketClient = null;


        socketClient = new Socket("127.0.0.1", 8888);
        InputStream in = socketClient.getInputStream();
        byte[] bytes = new byte[1024];

        int len = in.read(bytes);

        String msg = new String(bytes, 0, len);

        System.out.println(msg);
    }

}

2.2 完成客户端到服务端图片传输

Server 服务端等待客户端发送图片

package com.rrs.socketserver.server;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

import org.junit.Test;

/**
 * @author lzx
 *
 */
public class ServerPic {

	@Test
	public void serverPic() throws IOException {

		System.out.println("server start...");

		// 建立socket
		ServerSocket server = new ServerSocket(8899);

		// 阻塞式监听客户端
		Socket socket = server.accept();

		// 得到输入流
		InputStream in = socket.getInputStream();

		byte[] buf = new byte[1024];
		int len = 0;

		// 边读边写
		// 写到服务端磁盘上

		// 得到文件输出流
		File file = new File("java.jpg");
		FileOutputStream out = new FileOutputStream(file);

		while ((len = in.read(buf)) != -1) {

			out.write(buf, 0, len);
		}

		System.out.println("图片接受完毕...");
		
		socket.shutdownInput();
		in.close();
		out.close();
		

	}

}

Client 客户端发送图片

package com.rrs.socketserver.client;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;

import org.junit.Test;

/**
 * @author lzx
 *
 */
public class ClientPic {

	@Test
	public void clientPic() throws IOException {

		System.out.println("client start...");

		// 建立socket客户端
		Socket client = new Socket("127.0.0.1", 8899);

		// 从本地读取文件发送文件(边读边写)

		// 读取文件
		File file = new File("D:/Desktop/java.jpg");
		FileInputStream in = new FileInputStream(file);

		// 每次发送1k
		byte[] buf = new byte[1024];

		int len = 0;

		OutputStream out = client.getOutputStream();

		while ((len = in.read(buf)) != -1) {
			out.write(buf, 0, len);
		}
		System.out.println("图片发送完成...");

		out.close();
		in.close();
		client.shutdownOutput();

	}

}

2.3 完成模拟登陆

Server 服务端

package com.rrs.socketserver.server;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

import org.junit.Test;

import com.rrs.socketserver.pojo.User;

/**
 * @author lzx 模拟登陆服务端
 */
public class ServerLogin {

	@Test
	public void serverLogin() throws IOException, ClassNotFoundException {

		System.out.println("Server Start...");

		// 建立服务端socket
		ServerSocket server = new ServerSocket(8800);
		// 阻塞式监听客户端socket
		Socket socket = server.accept();

		InputStream in = socket.getInputStream();
		ObjectInputStream stream = new ObjectInputStream(in);

		User user = (User) stream.readObject();
		
		socket.shutdownInput();
		
		
		// 得到输出流反馈信息
		OutputStream out = socket.getOutputStream();
		
		String msg = "";
		
		if (user.getName().equals("张三") && user.getPassword() == 111111) {

			msg = "登陆成功";
		}else {
			msg = "登陆失败";
		}
		
		DataOutputStream outputStream = new DataOutputStream(out);
		outputStream.writeUTF(msg);
		
		socket.shutdownOutput();
		outputStream.close();
		out.close();
		stream.close();
		in.close();
		
	}

}

Client 客户端

package com.rrs.socketserver.client;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

import org.junit.Test;

import com.rrs.socketserver.pojo.User;

/**
 * @author lzx
 *  模拟登陆客户端
 */
public class ClientLogin {
	
	@Test
	public void  clientLogin() throws UnknownHostException, IOException {
		
		System.out.println("Client Start...");
		// 控制台输入用户名,密码
		Scanner scan = new Scanner(System.in);
		
		System.out.println("请输入用户名:");
		String name = scan.next();
		
		System.out.println("请输入密码:");
		int password = scan.nextInt();
		
		User user = new User(name, password);
		
		// 经过socket 传输
		Socket client  = new Socket("127.0.0.1", 8800);
		// 获取输出流
		OutputStream out = client.getOutputStream();
		ObjectOutputStream stream = new ObjectOutputStream(out);
		
		// 将对象写入流中
		stream.writeObject(user);
		
		client.shutdownOutput();
		
		// 接受消息
		InputStream in = client.getInputStream();
		DataInputStream inputStream = new DataInputStream(in);
		
		String msg = inputStream.readUTF();
		System.out.println(msg);
		client.shutdownInput();
		
		//关闭资源
		inputStream.close();
		in.close();
		stream.close();
		out.close();
	}

}

2.4 多线程优化服务端程序

  在以上咱们发现,服务端在被客户端链接一次后就结束运行了,那么咱们服务器在运行起来后是不须要关闭的,咱们可使用多线程来优化咱们的代码。java

建立一个登陆线程:

package com.rrs.socketserver.thread;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.net.Socket;

import com.rrs.socketserver.pojo.User;

/**
 * @author lzx
 *
 */
public class LoginThread extends Thread {

	private Socket socket;

	private InputStream in;
	private ObjectInputStream stream;
	private OutputStream out;

	public Socket getSocket() {
		return socket;
	}

	public LoginThread() {
		super();
	}

	public void setSocket(Socket socket) {
		this.socket = socket;
	}

	public LoginThread(Socket socket) {
		super();
		this.socket = socket;
	}

	@Override
	public void run() {

		// 得到输出流反馈信息
		try {
			in = socket.getInputStream();
			stream = new ObjectInputStream(in);

			User user = (User) stream.readObject();

			socket.shutdownInput();

			out = socket.getOutputStream();

			String msg = "";

			if (user.getName().equals("张三") && user.getPassword() == 111111) {

				msg = "登陆成功";
			} else {
				msg = "登陆失败";
			}

			DataOutputStream outputStream = new DataOutputStream(out);
			outputStream.writeUTF(msg);

			socket.shutdownOutput();
			outputStream.close();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (null != out) {
					out.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				if (null != stream) {
					stream.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				if (null != in) {
					in.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

}

server 服务端

package com.rrs.socketserver.server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import org.junit.Test;

import com.rrs.socketserver.thread.LoginThread;

/**
 * @author lzx 模拟登陆服务端
 */
public class ServerLogin {

	@Test
	public void serverLogin() throws IOException, ClassNotFoundException {

		System.out.println("Server Start...");

		// 建立服务端socket
		ServerSocket server = new ServerSocket(8800);

		int count = 1;

		while (true) {

			// 阻塞式监听客户端socket
			Socket socket = server.accept();
			new LoginThread(socket).start();
			System.out.println("第" + count + "个用户尝试登陆...");
			count++;
		}
	}

}

  以上只是一个简单的入门例子,在实际开发中若是多个用户都同时访问服务端则会开启多个线程形成服务器压力,所以能够尝试使用线程池来优化。服务器

相关文章
相关标签/搜索