传统tcp网络编程入门示例

1.demo

 

public class Server {
	public static void main(String[] args) throws IOException {
		// 创建一个ServerSocket,用于监听客户端Socket的连接请求
		ServerSocket ss = new ServerSocket(30000);
		// 采用循环不断接受来自客户端的请求
		while (true) {
			// 每当接受到客户端Socket的请求,服务器端也对应产生一个Socket
			Socket s = ss.accept();
			// 方式一
			PrintStream ps = new PrintStream(s.getOutputStream());
			ps.println("hello,您收到了服务器的问候!");// 进行普通IO操作
			ps.close();
			s.close();
			// 方式二
			BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
			bw.write("hello,您收到了服务器的问候!\n");// 必须同时加上\n和flush,客户端用readLine才能输出
			bw.flush();
			// 方式三
			BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
			System.out.println("来自客户端的数据:" + br.readLine());
		}
	}
}

public class Client {
	public static void main(String[] args) throws IOException {
		Socket socket = new Socket("127.0.0.1", 30000);
		// 方式一、二
		BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		String line = br.readLine();
		System.out.println("来自服务器的数据:" + line);
		br.close();
		socket.close();
		// 方式三
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
		bw.write("hello,您收到了客户端的问候!");// 只需要加flush,服务器端用readLine就能输出
		bw.flush();
	}
}

2.半关闭的Socket

 

 

public class Server {
	public static void main(String[] args) throws Exception {
		ServerSocket ss = new ServerSocket(30000);
		Socket socket = ss.accept();
		PrintStream ps = new PrintStream(socket.getOutputStream());
		ps.println("服务器的第一行数据");
		ps.println("服务器的第二行数据");
		// 关闭socket的输出流,表明输出数据已经结束
		socket.shutdownOutput();
		// 下面语句将输出false,表明socket还未关闭。
		System.out.println(socket.isClosed());
		Scanner scan = new Scanner(socket.getInputStream());
		while (scan.hasNextLine()) {
			System.out.println(scan.nextLine());
		}
		scan.close();
		socket.close();
		ss.close();
	}
}

public class Client {
	public static void main(String[] args) throws Exception {
		Socket s = new Socket("localhost", 30000);
		Scanner scan = new Scanner(s.getInputStream());
		while (scan.hasNextLine()) {
			System.out.println(scan.nextLine());
		}
		PrintStream ps = new PrintStream(s.getOutputStream());
		ps.println("客户端的第一行数据");
		ps.println("客户端的第二行数据");
		ps.close();
		scan.close();
		s.close();
	}
}

3.ByteArrayOutputStream

PrintStream的write方法是可以用的,只不过要在后面加上输出\n,否则就用它的println,否则因为接收端用的是nextLine()会因为没有末尾的换行
而读取不到数据;但用字节的方式接收的话就不必关心末尾有没有\n了

 

public class Server {
	public static void main(String[] args) throws Exception {
		ServerSocket server = new ServerSocket(30000);
		while (true) {
			Socket socket = server.accept();
			PrintStream ps = new PrintStream(socket.getOutputStream());
			ps.write("这是测试么?".getBytes());
			ps.println("这是测试么??");
			ps.print("这是测试么??");
			socket.shutdownOutput();// 必须关闭,否则客户端会阻塞在read方法上
		}
	}

}

public class Client {
	public static void main(String[] args) throws Exception {
		Socket socket = new Socket("127.0.0.1", 30000);
		InputStream is = socket.getInputStream();
		byte[] bytes = new byte[1024];
		ByteArrayOutputStream bout = new ByteArrayOutputStream();
		int len;
		while (true) {
			len = is.read(bytes);
			System.out.println("len = " + len);
			if (len < 0) {
				break;
			}
			bout.write(bytes, 0, len);
		}
		System.out.println(bout.size());
		System.out.println(bout.toString());
	}
}

 

4.多线程

public class MyServer {
	// 定义保存所有Socket的ArrayList,并将其包装为线程安全的
	public static List<Socket> socketList = Collections.synchronizedList(new ArrayList<Socket>());

	public static void main(String[] args) throws IOException {
		ServerSocket ss = new ServerSocket(30000);
		while (true) {
			// 此行代码会阻塞,将一直等待别人的连接
			Socket s = ss.accept();
			socketList.add(s);
			// 每当客户端连接后启动一条ServerThread线程为该客户端服务
			new Thread(new ServerThread(s)).start();
		}
	}
}

// 负责处理每个线程通信的线程类
public class ServerThread implements Runnable {
	// 定义当前线程所处理的Socket
	Socket s = null;
	// 该线程所处理的Socket所对应的输入流
	BufferedReader br = null;

	public ServerThread(Socket s) throws IOException {
		this.s = s;
		// 初始化该Socket对应的输入流
		br = new BufferedReader(new InputStreamReader(s.getInputStream()));
	}

	public void run() {
		try {
			String content = null;
			// 采用循环不断从Socket中读取客户端发送过来的数据
			while ((content = readFromClient()) != null) {
				// 遍历socketList中的每个Socket,
				// 将读到的内容向每个Socket发送一次
				for (Socket s : MyServer.socketList) {
					PrintStream ps = new PrintStream(s.getOutputStream());
					ps.println(content);
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	// 定义读取客户端数据的方法
	private String readFromClient() {
		try {
			return br.readLine();
		}
		// 如果捕捉到异常,表明该Socket对应的客户端已经关闭
		catch (IOException e) {
			// 删除该Socket。
			MyServer.socketList.remove(s); // ①
		}
		return null;
	}
}

public class MyClient {
	public static void main(String[] args) throws Exception {
		Socket s = new Socket("127.0.0.1", 30000);
		// 客户端启动ClientThread线程不断读取来自服务器的数据
		new Thread(new ClientThread(s)).start(); // ①
		// 获取该Socket对应的输出流
		PrintStream ps = new PrintStream(s.getOutputStream());
		String line = null;
		// 不断读取键盘输入
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		while ((line = br.readLine()) != null) {
			// 将用户的键盘输入内容写入Socket对应的输出流
			ps.println(line);
		}
	}
}

public class ClientThread implements Runnable {
	// 该线程负责处理的Socket
	private Socket s;
	// 该线程所处理的Socket所对应的输入流
	BufferedReader br = null;

	public ClientThread(Socket s) throws IOException {
		this.s = s;
		br = new BufferedReader(new InputStreamReader(s.getInputStream()));
	}

	public void run() {
		try {
			String content = null;
			// 不断读取Socket输入流中的内容,并将这些内容打印输出
			while ((content = br.readLine()) != null) {
				System.out.println(content);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

参考:

 

疯狂java讲义
 

posted @ 2017-04-05 22:26  john8169  阅读(121)  评论(0编辑  收藏  举报