socket通信初级篇——服务员与客人

socket位于TCP/IP协议的传输层协议。相对于应用层的http协议,更低了一层。

通过服务员与客人的交互,学习一下socket

一、第一个场景

1、服务器端代码:

package me.net;

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

/**
 * Socket作用就是client端与server端通信。可以理解成客人与服务员之间以一定的规则说话。
 *
 * 场景1:一个客人,一个服务员。
 *
 * @author 3111
 *
 */
public class ServerA {

/**
 * 服务员,提供服务
 *
 * 创建server端过程:Server端运行使用的ip为当前设备的ip,端口号可以随便指定。不要和保留的重复。
 * 雇佣一个服务员,告诉服务员,站在大门口,凡是在大门口进来的都是客人,后门进的,不是客人。大门口进来的,要打招呼。
 *
 * @param args
 * @throws IOException
 */
public static void main(String[] args) {
	// 指定一个端口号,这就是大门口
	try {
		ServerSocket serverSocket = new ServerSocket(9999);
		// 等客来
		Socket socket = serverSocket.accept();

		System.err.println("有人来了,看样子是本地人。ip是:" + socket.getInetAddress()
				+ "。端口号是:" + socket.getPort());

		// server端,向外输出数据。来客了,服务员得说话
		OutputStream os = socket.getOutputStream();
		// 封装一下
		DataOutputStream dos = new DataOutputStream(os);

		// 向客户端说一句话,你连上来了。
		dos.writeUTF("欢迎光临,你已经连上了!看样子你是本地人:你ip是:" + socket.getInetAddress()
				+ "。你的端口号是:" + socket.getPort());
		dos.writeUTF("大牛笔记!www.weixuehao.com");
		dos.flush();

		// 下面就是释放各种资源了。
		// 关dos,os,socket
		dos.close();
		os.close();
		socket.close();
		serverSocket.close();
	} catch (IOException e) {
		System.err.println(e.getMessage());
	}
}
}

 

2、客户端代码:

package me.net;

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

public class ClientA {

/**
 * 连上socket。告诉socket,连什么ip,什么端口。然后就行了。 客人要知道,今晚去哪吃,进哪个门才对。
 *
 * @param args
 */
public static void main(String[] args) {
	try {
		// ip,端口,哪个店铺的,哪个大门。
		Socket socket = new Socket("localhost", 9999);

		// 客户端收到服务器的消息,所以是输入。客人刚进门,听到服务员说话。
		InputStream is = socket.getInputStream();
		DataInputStream dis = new DataInputStream(is);
		// 看看收到服务器端什么东西
		System.err.println(dis.readUTF());
		System.err.println(dis.readUTF());

		// 释放资源
		dis.close();
		is.close();
		socket.close();
	} catch (IOException e) {
		System.err.println(e.getMessage());
	}
}
}

 

二、第二个场景

1、服务器端代码:

package me.net;

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

/**
 * Socket作用就是client端与server端通信。可以理解成客人与服务员之间以一定的规则说话。
 *
 * 场景2:多个客人,一个服务员。来一个客人,说一句话。其实就是加个循环语句。
 *
 * @author 3111
 *
 */
public class ServerB {

/**
 * 服务员,提供服务
 *
 * 创建server端过程:Server端运行使用的ip为当前设备的ip,端口号可以随便指定。不要和保留的重复。
 * 雇佣一个服务员,告诉服务员,站在大门口,凡是在大门口进来的都是客人,后门进的,不是客人。大门口进来的,要打招呼。
 *
 * @param args
 * @throws IOException
 */
public static void main(String[] args) {
	// 指定一个端口号,这就是大门口
	try {
		ServerSocket serverSocket = new ServerSocket(9999);

		// 在这里加个循环语句,服务员一直在大门口站着
		while (true) {

			// 等客来
			Socket socket = serverSocket.accept();

			System.err
					.println("有人来了,看样子是本地人。ip是:" + socket.getInetAddress()
							+ "。端口号是:" + socket.getPort());
			// server端,向外输出数据。来客了,服务员得说话
			OutputStream os = socket.getOutputStream();
			// 封装一下
			DataOutputStream dos = new DataOutputStream(os);

			// 向客户端说一句话,你连上来了。
			dos.writeUTF("欢迎光临,你已经连上了!看样子你是本地人:你ip是:"
					+ socket.getInetAddress() + "。你的端口号是:"
					+ socket.getPort());
			dos.writeUTF("大牛笔记!www.weixuehao.com");
			dos.flush();

			// 下面就是释放各种资源了。
			// 关dos,os,socket
			dos.close();
			os.close();
			socket.close();
		}
		// serverSocket.close();
	} catch (IOException e) {
		System.err.println(e.getMessage());
	}
}
}

 

2、客户端代码:

package me.net;

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

public class ClientB {

/**
 * 连上socket。告诉socket,连什么ip,什么端口。然后就行了。 客人要知道,今晚去哪吃,进哪个门才对。
 *
 * @param args
 */
public static void main(String[] args) {
	try {
		// ip,端口,哪个店铺的,哪个大门。
		Socket socket = new Socket("localhost", 9999);

		// 客户端收到服务器的消息,所以是输入。客人刚进门,听到服务员说话。
		InputStream is = socket.getInputStream();
		DataInputStream dis = new DataInputStream(is);
		// 看看服务员说什么了
		System.err.println(dis.readUTF());
		System.err.println(dis.readUTF());

		// 释放资源
		dis.close();
		is.close();
		socket.close();
	} catch (IOException e) {
		System.err.println(e.getMessage());
	}
}
}

 

三、第三个场景

1、服务器端代码:

package me.net;

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

/**
 * Socket作用就是client端与server端通信。可以理解成客人与服务员之间以一定的规则说话。
 *
 * 场景3:一个客人,一个服务员。来一个客人,服务员只说一句话。不太过瘾?客人也要说话,然后 服务员给一个响应的反馈,类似于机器人。
 * 或可以理解成,微信的关键词,输入,然后返回对应的内容。
 *
 * @author 3111
 *
 */
public class ServerC {

/**
 * 服务员,提供服务
 *
 * 创建server端过程:Server端运行使用的ip为当前设备的ip,端口号可以随便指定。不要和保留的重复。
 * 雇佣一个服务员,告诉服务员,站在大门口,凡是在大门口进来的都是客人,后门进的,不是客人。大门口进来的,要打招呼。
 *
 * @param args
 */
public static void main(String[] args) {
	// 指定一个端口号,这就是大门口
	try {
		ServerSocket serverSocket = new ServerSocket(9999);

		// 在这里加个循环语句,服务员一直在大门口站着

		// 等客来
		Socket socket = serverSocket.accept();
		System.err.println("有人来了,看样子是本地人。ip是:" + socket.getInetAddress()
				+ "。端口号是:" + socket.getPort());

		// server端,向外输出数据。来客了,服务员得向客人说话
		OutputStream os = socket.getOutputStream();
		// 封装一下
		DataOutputStream dos = new DataOutputStream(os);

		// server端,接收数据。听听客人说什么话。
		InputStream is = socket.getInputStream();
		DataInputStream dis = new DataInputStream(is);

		String clientSay = "";
		while (true) {
			// 服务员一直在听客人说什么
			clientSay = dis.readUTF();
			System.err.println("这小子说:" + clientSay);
			if (clientSay.equals("bye")) {
				break;
			}
			// 向客户端说一句话,你连上来了。
			dos.writeUTF("欢迎光临,你已经连上了!看样子你是本地人:你ip是:"
					+ socket.getInetAddress() + "。你的端口号是:"
					+ socket.getPort());
			dos.writeUTF("大牛笔记!www.weixuehao.com");
			dos.writeUTF("小子,你@#$@#$……再说一遍   #" + clientSay + "##  试试!");
			dos.flush();

		}
		// 下面就是释放各种资源了。
		// 关dos,os,socket
		dos.close();
		os.close();
		socket.close();
		serverSocket.close();
	} catch (IOException e) {
		System.err.println(e.getMessage());
	}
}
}

 

2、客户端代码:

package me.net;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;

public class ClientC {

/**
 * 连上socket。告诉socket,连什么ip,什么端口。然后就行了。 客人要知道,今晚去哪吃,进哪个门才对。
 *
 * @param args
 */
public static void main(String[] args) {
	try {
		// ip,端口,哪个店铺的,哪个大门。
		Socket socket = new Socket("localhost", 9999);

		// 客户端收到服务器的消息,所以是输入。客人刚进门,听到服务员说话。
		InputStream is = socket.getInputStream();
		DataInputStream dis = new DataInputStream(is);

		// 客人向服务员说...
		OutputStream os = socket.getOutputStream();
		DataOutputStream dos = new DataOutputStream(os);

		// 客人自己打字。接收键盘的输入读取键盘输入流
		InputStreamReader isr = new InputStreamReader(System.in);
		// 封装键盘输入流
		BufferedReader br = new BufferedReader(isr);

		String clientSay = "";
		while (true) {
			// 所以下面需要客人自己说了,自己打字了
			clientSay = br.readLine();

			// 这个位置,最好和服务员那对应。
			if (clientSay.equals("bye")) {
				break;
			}
			// 告诉客服你刚才想什么了
			dos.writeUTF(clientSay);
			dos.flush();

			// 听听服务员说什么了,这里输出和服务员那里数量要一样。要不然,就卡在这里了。
			System.err.println(dis.readUTF());
			System.err.println(dis.readUTF());
			System.err.println(dis.readUTF());
		}

		// 释放资源
		dis.close();
		is.close();
		socket.close();
	} catch (IOException e) {
		System.err.println(e.getMessage());
	}
}
}

 

四、第四个场景

1、服务器端代码:

package me.net;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * Socket作用就是client端与server端通信。可以理解成客人与服务员之间以一定的规则说话。
 *
 * 场景4:一个客人,一个服务员。聊会天吧。俩人都说。都听。
 * 也就是服务员有俩线程。客人也有俩线程。服务员的听线程,对应客人的说线程。服务员的说线程,对应客人的听线程。
 *
 * @author 3111
 *
 */
public class ServerD {

	/**
	 * 服务员,提供服务
	 *
	 * 创建server端过程:Server端运行使用的ip为当前设备的ip,端口号可以随便指定。不要和保留的重复。
	 * 雇佣一个服务员,告诉服务员,站在大门口,凡是在大门口进来的都是客人,后门进的,不是客人。大门口进来的,要打招呼。
	 *
	 * @param args
	 * @throws IOException
	 */
	public static void main(String[] args) {
		// 指定一个端口号,这就是大门口
		try {
			ServerSocket serverSocket = new ServerSocket(9999);

			// 在这里加个循环语句,服务员一直在大门口站着

			// 等客来
			Socket socket = serverSocket.accept();
			System.err.println("有人来了,看样子是本地人。ip是:" + socket.getInetAddress()
					+ "。端口号是:" + socket.getPort());

			// server端,向外输出数据。来客了,服务员得向客人说话
			OutputStream os = socket.getOutputStream();
			// 封装一下
			DataOutputStream dos = new DataOutputStream(os);

			// server端,接收数据。听听客人说什么话。
			InputStream is = socket.getInputStream();
			DataInputStream dis = new DataInputStream(is);

			new ServerIsListening(dis).start();
			new ServerIsSaying(dos).start();

			// 下面就是释放各种资源了。
			// 关dos,os,socket
			// dos.close();
			// os.close();
			// socket.close();
			// serverSocket.close();
		} catch (IOException e) {
			System.err.println(e.getMessage());
		}
	}

}

class ServerIsListening extends Thread {
	private DataInputStream dis;

	public ServerIsListening(DataInputStream dis) {
		this.dis = dis;
	}

	public void run() {
		String clientSay = "";
		try {
			while (true) {
				clientSay = dis.readUTF();
				System.err.println("客人说:" + clientSay);
				if (clientSay.equals("bye")) {
					System.err.println("客官慢走~");
					System.exit(0);
				}
			}
		} catch (Exception e) {
			System.err.println(e.getMessage());
		}
	}
}

class ServerIsSaying extends Thread {
	private DataOutputStream dos;

	public ServerIsSaying(DataOutputStream dos) {
		this.dos = dos;
	}

	public void run() {
		InputStreamReader isr = new InputStreamReader(System.in);
		BufferedReader br = new BufferedReader(isr);

		String serverSay = "";
		try {
			while (true) {

				serverSay = br.readLine();
				dos.writeUTF(serverSay);
				if (dos.equals("bye")) {
					System.err.println("不好意思,我下班了!");
					System.exit(0);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

 

2、客户端代码:

package me.net;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;

public class ClientD {

	/**
	 * 连上socket。告诉socket,连什么ip,什么端口。然后就行了。 客人要知道,今晚去哪吃,进哪个门才对。
	 *
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			// ip,端口,哪个店铺的,哪个大门。
			Socket socket = new Socket("localhost", 9999);

			// 客户端收到服务器的消息,所以是输入。客人刚进门,听到服务员说话。
			InputStream is = socket.getInputStream();
			DataInputStream dis = new DataInputStream(is);

			// 客人向服务员说...
			OutputStream os = socket.getOutputStream();
			DataOutputStream dos = new DataOutputStream(os);

			new ClientSay(dos).start();
			new ClientListen(dis).start();

			// //释放资源
			// dis.close();
			// is.close();
			// socket.close();
		} catch (IOException e) {
			System.err.println(e.getMessage());
		}
	}
}

class ClientListen extends Thread {
	private DataInputStream dis;

	public ClientListen(DataInputStream dis) {
		this.dis = dis;
	}

	public void run() {
		String serverSay = "";
		try {
			while (true) {
				serverSay = dis.readUTF();
				System.err.println("服务员说:" + serverSay);
				if (serverSay.equals("bye")) {
					System.err.println("服务员下班走人了。");
					System.exit(0);
				}
			}
		} catch (Exception e) {
			e.getMessage();
		}
	}
}

class ClientSay extends Thread {
	private DataOutputStream dos;

	public ClientSay(DataOutputStream dos) {
		this.dos = dos;
	}

	public void run() {
		InputStreamReader isr = new InputStreamReader(System.in);
		BufferedReader br = new BufferedReader(isr);

		String str = "";
		try {
			while (true) {
				str = br.readLine();
				dos.writeUTF(str);
				if (str.equals("bye")) {
					System.err.println("客人自己走了");
					System.exit(0);
				}
			}
		} catch (Exception e) {

		}
	}
}