码迷,mamicode.com
首页 > 编程语言 > 详细

java进阶 ------ 基于Socket低层次网络编程

时间:2015-04-19 01:12:51      阅读:150      评论:0      收藏:0      [点我收藏+]

标签:socket实现   多线程实现socket通信   

[本文是自己学习所做笔记,欢迎转载,但请注明出处:http://blog.csdn.net/jesson20121020]

Socket通讯:

  网络上的两个程序通过一个双向的通讯连接实现数据的交互,这个双向链路的一端称为一个Socket。Socket通常用来实现客户方和服务方的连接。Socket是TCP/IP协议的一个十分流行的编程界面,一个Socket由一个IP地址和一个端口号唯一确定。

  在传统的UNIX环境下可以操作TCP/IP协议的接口不止Socket一个,Socket所支持的协议种类不光是TCP/IP一种,因此两者之间没有必然的联系。在java环境下,Socket编主要是基于TCP/IP协议的网络编程。


Socket通讯的一般过程:

  使用Socket进行Client/Server程序设计的一般连接过程是这样的:Server端Listen(监听)某个端口是否有连接请求,Client端向Server端发回Connect(连接请求), Server端向Client端发回Accept(接受)消息。一个连接就建立起来了。Server端和Client端都可以通过Send,Write等方法与对方通信。

  对于一个功能齐全的Socket,都要包含以下基本结构,其工作过程包含以下四个基本的步骤:

  (1). 创建Socket;

  (2). 打开连接到Socket的输入/出流。

  (3). 按照一定的协议对Socket进行读/写操作。

  (4). 关闭Socket。


创建Socket:

  java在java.net中提供了两个类Socket和ServerSocket,分别用来表示双向连接的客户端和服务端。这是两个封装得非常好的类,使用很方便,构造方法如下:

Socket();

Socket(Proxy proxy);

Socket(InetAddress address,int port);

Socket(InetAddress address,int port,boolean stream);

Socket(String host,int port);

Socket(String host,int port,boolean stream);

Socket(SocketInmpl impl);

Socket(String host,int port,InetAddress localAddr,int localPort);

Socket(InetAddress address,int port,InetAddress localAddr,int localPort);

ServerSocket();

ServerSocket(int port);

ServerSocket(int port,int backup);

ServerSocket(int port,int backup,InetAddress bindAddr);

  其中,address,host和port分别是双向连接中另一方的ip地址,主机名和端口号,stream指明socket是流socket还是数据报socket,localPort表示本地主机的端口号,localAddr和bindAddr是本地机器的的地址,impl是socket的父类,既可以用来创建serverSocket又可以用来创建Socket。如:

Socket client  = new Socket("127.0.0.1",2000);

ServerSocket server = new ServerSocket(2000);

  注意,在选择端口时,需要小心,每个端口提供的一种特定的服务,只有给出正确的端口,才能获得相应的服务,0~1023为系统保留,如http服务端口号80,telent服务端口号21,所以我们在选择端口时,最好选择一个大于1023的数,以防止冲突。


用Socket实现客户端与服务端交互:

  单线程实现:

   如果,客户端与服务端均采用单线程实现通信,则每次双方只能发送一条信息,即按:client发-server收-server发-client收.......这种模式进行通讯,可以观察下列单线程实现代码输出结果:


客户端代码SocketTalkClient.java:

package com.jesson.mianshi.network;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class SocketTalkClient {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		SocketTalkClient client = new SocketTalkClient();
		// 测试单线程实现的客户端与服务端交互
		System.out.println("client: 单线程........");
		client.singleThreadTalkClient();
	}

	/**
	 * 单线程实现的客户端与服务端通信
	 */
	public void singleThreadTalkClient() {
		try {
			Socket socket = new Socket("127.0.0.1", 4700);
			// 向本机的4700端口发出客户请求
			BufferedReader sin = new BufferedReader(new InputStreamReader(
					System.in));
			// 由系统标准输入设备构造BufferedReader对象
			PrintWriter os = new PrintWriter(socket.getOutputStream());
			// 由Socket对象得到输出流,并构造PrintWriter对象
			BufferedReader is = new BufferedReader(new InputStreamReader(
					socket.getInputStream()));
			// 由Socket对象得到输入流,并构造相应的BufferedReader对象
			String readline;
			readline = sin.readLine(); // 从系统标准输入读入一字符串
			while (!readline.equals("bye")) {
				os.println(readline);
				// 将从系统标准输入读入的字符串输出到Server
				os.flush();
				// 刷新输出流,使Server马上收到该字符串
				System.out.println("Client: " + readline);
				try {
					System.out.println("Server: " + is.readLine());
				} catch (IOException e) {
					readline = sin.readLine();
					continue;
				}
				readline = sin.readLine(); // 从系统标准输入读入一字符串
			} // 继续循环

			os.close(); // 关闭Socket输出流
			is.close(); // 关闭Socket输入流
			socket.close(); // 关闭Socket
		} catch (Exception e) {
			System.out.println("error");
		}
	}
}

服务端代码SocketTalkServer.java:

package com.jesson.mianshi.network;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class SocketTalkServer {

	public static void main(String[] args) {
		SocketTalkServer server = new SocketTalkServer();
		// 测试单线程实现的客户端与服务端交互
		System.out.println("server: 单线程........");
		server.singleThreadTalkServer();
	}

	/**
	 * 单线程实现的客户端与服务端通信
	 */
	public void singleThreadTalkServer() {
		ServerSocket server = null;
		try {
			server = new ServerSocket(4700);

		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.out.println("can not listen to:" + e);
		}
		Socket socket = null;
		try {
			socket = server.accept();

		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.out.println("can not accept socket from client:" + e);
		}
		String line;
		try {

			BufferedReader is = new BufferedReader(new InputStreamReader(
					socket.getInputStream()));
			PrintStream os = new PrintStream(socket.getOutputStream());
			BufferedReader sin = new BufferedReader(new InputStreamReader(
					System.in));
			System.out.println("client: " + is.readLine());

			line = sin.readLine();
			while (!line.equals("bye")) {
				os.println(line);
				os.flush();
				System.out.println("Server: " + line);
				System.out.println("Client: " + is.readLine());
				line = sin.readLine();
			}
			os.close();
			is.close();
			socket.close();
			server.close();

		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.out.println("error: " + e);
		}
	}
}
  程序执行输出结果:

客户端输出:

client: 单线程........
hello server
Client: hello server
Server: hello cient
我每次只能发送一条消息
Client: 我每次只能发送一条消息
Server: 我也是

服务端输出:

<span style="font-size:14px;">server: 单线程........
client: hello server
hello cient
Server: hello cient
Client: 我每次只能发送一条消息
我也是
Server: 我也是</span>

  多线程实现:

  可以看出,用单线程实现,客户端每次只能发送一条消息,要实现双方都可以发送任意条消息,这就需要用到多个线程了,这里用了两个线程来实现监听和写。代码如下:

客户端代码(SocketTalkClient.java):

package com.jesson.mianshi.network;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class SocketTalkServer {

	public static void main(String[] args) {
		SocketTalkServer server = new SocketTalkServer();

		// 测试多线程实现的客户端与服务端交互
		System.out.println("server: 多线程........");
		server.MultiThreadTalkServer();
	}

	/**
	 * 多线程实现的客户端与服务端交互
	 */
	private void MultiThreadTalkServer() {
		ServerSocket server = null;
		try {
			server = new ServerSocket(4701);

		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.out.println("can not listen to:" + e);
		}
		Socket socket = null;
		try {
			socket = server.accept();

		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.out.println("can not accept socket from client:" + e);
		}
		String line;
		try {

			BufferedReader is = new BufferedReader(new InputStreamReader(
					socket.getInputStream()));
			PrintWriter os = new PrintWriter(socket.getOutputStream());
			BufferedReader sin = new BufferedReader(new InputStreamReader(
					System.in));

			new ServerLinstenThread(is).start();
			new ServerWriteThread(sin, os).start();

			/*
			 * os.close(); is.close(); socket.close(); server.close();
			 */

		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.out.println("error: " + e);
		}
	}

	/**
	 * 服务端听线程
	 * 
	 * @author jesson
	 * 
	 */
	class ServerLinstenThread extends Thread {
		private BufferedReader linsten;

		public ServerLinstenThread(BufferedReader linsten) {
			// TODO Auto-generated constructor stub
			this.linsten = linsten;
		}

		public void run() {
			// TODO Auto-generated method stub
			String clientInfo;
			try {

				while (true) {
					clientInfo = linsten.readLine();
					System.out.println("Client: " + clientInfo);
					if (clientInfo.equals("bye")) {
						System.out.println("Client下线,程序退出");
						System.exit(0);
					}
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	/**
	 * 服务端端写线程
	 * 
	 * @author jesson
	 * 
	 */
	class ServerWriteThread extends Thread {

		private BufferedReader writer;
		private PrintWriter printWriter;

		public ServerWriteThread(BufferedReader writer, PrintWriter printWriter) {
			this.writer = writer;
			this.printWriter = printWriter;
		}

		public void run() {
			// TODO Auto-generated method stub
			String serverInfo;
			try {
				while (true) {
					serverInfo = writer.readLine();
					printWriter.println(serverInfo);
					printWriter.flush();
					System.out.println("Server: " + serverInfo);
					if (serverInfo.equals("bye")) {
						System.out.println("Server自己下线,程序退出");
						System.exit(0);
					}
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}

	}
}
服务端代码(SocketTalkServer.java):

package com.jesson.mianshi.network;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class SocketTalkServer {

	public static void main(String[] args) {
		SocketTalkServer server = new SocketTalkServer();

		// 测试多线程实现的客户端与服务端交互
		System.out.println("server: 多线程........");
		server.MultiThreadTalkServer();
	}

	/**
	 * 多线程实现的客户端与服务端交互
	 */
	private void MultiThreadTalkServer() {
		ServerSocket server = null;
		try {
			server = new ServerSocket(4701);

		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.out.println("can not listen to:" + e);
		}
		Socket socket = null;
		try {
			socket = server.accept();

		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.out.println("can not accept socket from client:" + e);
		}
		String line;
		try {

			BufferedReader is = new BufferedReader(new InputStreamReader(
					socket.getInputStream()));
			PrintWriter os = new PrintWriter(socket.getOutputStream());
			BufferedReader sin = new BufferedReader(new InputStreamReader(
					System.in));

			new ServerLinstenThread(is).start();
			new ServerWriteThread(sin, os).start();

			/*
			 * os.close(); is.close(); socket.close(); server.close();
			 */

		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.out.println("error: " + e);
		}
	}

	/**
	 * 服务端听线程
	 * 
	 * @author jesson
	 * 
	 */
	class ServerLinstenThread extends Thread {
		private BufferedReader linsten;

		public ServerLinstenThread(BufferedReader linsten) {
			// TODO Auto-generated constructor stub
			this.linsten = linsten;
		}

		public void run() {
			// TODO Auto-generated method stub
			String clientInfo;
			try {

				while (true) {
					clientInfo = linsten.readLine();
					System.out.println("Client: " + clientInfo);
					if (clientInfo.equals("bye")) {
						System.out.println("Client下线,程序退出");
						System.exit(0);
					}
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	/**
	 * 服务端端写线程
	 * 
	 * @author jesson
	 * 
	 */
	class ServerWriteThread extends Thread {

		private BufferedReader writer;
		private PrintWriter printWriter;

		public ServerWriteThread(BufferedReader writer, PrintWriter printWriter) {
			this.writer = writer;
			this.printWriter = printWriter;
		}

		public void run() {
			// TODO Auto-generated method stub
			String serverInfo;
			try {
				while (true) {
					serverInfo = writer.readLine();
					printWriter.println(serverInfo);
					printWriter.flush();
					System.out.println("Server: " + serverInfo);
					if (serverInfo.equals("bye")) {
						System.out.println("Server自己下线,程序退出");
						System.exit(0);
					}
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}
	}
}

  执行上述代码,运行结果:

客户端输出:

client: 多线程........
你好,server
Client: 你好,server
Server: 你好,client
Server: server发送多条信息:
Server: 1. abcd
Server:  2. 1234
Server:  3. ABC
client发送多条消息:
Client: client发送多条消息:
1. xxxxx
Client: 1. xxxxx
2.yyyy
Client: 2.yyyy
3.zzzz
Client: 3.zzzz
bye
Client: bye
Client自己下线,程序退出

服务端输出:

server: 多线程........
Client: 你好,server
你好,client
Server: 你好,client
server发送多条信息:
Server: server发送多条信息:
1. abcd
Server: 1. abcd
 2. 1234
Server:  2. 1234
 3. ABC
Server:  3. ABC
Client: client发送多条消息:
Client: 1. xxxxx
Client: 2.yyyy
Client: 3.zzzz
Client: bye
Client下线,程序退出
  


java进阶 ------ 基于Socket低层次网络编程

标签:socket实现   多线程实现socket通信   

原文地址:http://blog.csdn.net/jesson20121020/article/details/45111813

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!