java进阶 ------ 基于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下线,程序退出

  

时间: 2024-12-31 03:35:51

java进阶 ------ 基于Socket低层次网络编程的相关文章

java进阶 ------ 基于URL高层次的网络编程

[本文是自己学习所做笔记,欢迎转载,但请注明出处:http://blog.csdn.net/jesson20121020] 统一资源定位符URL URL(Uniform Resource Locator)表示Internet上某一资源的地址,通过URL我们可以访问internet上的各种网络资源,比如最常见的WWW,FTP站点. URL的组成: protocol://resourceName 协议名(protocol)指明获取资源所使用的传输协议,如http,ftp,gopher,file等,资

基于Socket实现网络编程

Socket是网络上两个程序间双向通讯的一端,它既可以发送请求,也可以接收请求,利用它可以方便的编写网络上数据的传递,在java中,有专门的类类处理用户的请求和响应.利用Socket 类的方法,就可以实现两台计算机之间的通信,那么怎么利用socket进行网络编程呢?我试试水~ 网络中的进程之间是如何进行通信的? 本地进程间通信(IPC)有很多种方法,简而言之可以归结为以下四类: 消息传递(管道,FIFO,消息队列); 同步(互斥量,条件变量,读写锁,文件和写记录锁,信号量): 内存共享(匿名的和

Java中基于HTTP协议网络编程

java中为我们的网络支持提供了java.net包,能够使我们以编程的方式来訪问Web服务功能,这篇博客,就跟大家分享一下.Java中的网络编程的知识.主要是学习下该java.net包下的API. URI-->URL URI:表示的是统一的资源标识,它是以某种统一的方式标识资源的简单字符串. 这样的字符串以scheme开头. URL:表示统一的资源定位器的任务,URL是一种URI. URN:一般不能为资源提供持久不变的名称.这是统一的资源命名的任务.URN也是一种URI,但它是全球唯一的.持久不

分布式计算(一)——Java进阶与Socket通讯

1.解释 RuntimeException.例举它的1-2个之类,并用一个小程序验证捕获并处理异常的过程. 错运行时异常都是 RuntimeException 类及其子类异常.这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理,但 程序应该从逻辑角度尽可能避免这类异常的发生. 如NullPointerException . IndexOutOfBoundsException 等 2.在生产实践中,每个业务模块都会定义一个异常基类,例如 Account 模块定义 AccountExcept

初解,Scala语言中基于Actor的并发编程的机制,并展示了在Spark中基于Scala语言的Actor而产生的消息驱动框架Akka的使用,

Scala深入浅出实战中级--进阶经典(第66讲:Scala并发编程实战初体验及其在Spark源码中应用解析)内容介绍和视频链接 2015-07-24 DT大数据梦工厂 从明天起,做一个勤奋的人 看视频.下视频,分享视频 DT大数据梦工厂-Scala深入浅出实战中级--进阶经典:第66讲:Scala并发编程实战初体验及其在Spark源码中的应用解析 本期视频通过代码实战详解了Java语言基于加锁的并发编程模型的弊端以及Scala语言中基于Actor的并发编程的机制,并展示了在Spark中基于Sc

Java网络编程之TCP网络编程

一.基于Socket的TCP编程 Java语言的基于套接字编程分为服务端编程和客户端编程,其通信模型如图所示: 二.客户端Socket的工作过程(四个基本步骤) 1.创建Socket根据指定服务端的IP地址或端口号构造Socket类对象.若服务器端响应,则建立客户端到服务器的通信线路:若连接失败,会出现异常.2.打开连接到Socket的输入出流使用getlnputStream()方法获得输入流,使用getOutputStream()方法获得输出流,进行数据传输.3.按照一定的协议对Socket

基于java的简单Socket编程

1TCP协议与UDP协议     1.1 TCP               TCP是(Tranfer Control Protocol)的简称,是一种面向连接的保证可靠传输的协议.通过TCP协议传输,得到的是一个顺序的无差错的数据流.发送方和接收方的成对的两个socket之间必须建立连接,当一个socket(通常都是server socket)等待建立连接时,另一个socket可以要求进行连接,一旦这两个socket连接起来,它们就可以进行双向数据传输,双方都可以进行发送或接收操作. TCP的

读懂Java中的Socket编程(转)

Socket,又称为套接字,Socket是计算机网络通信的基本的技术之一.如今大多数基于网络的软件,如浏览器,即时通讯工具甚至是P2P下载都是基于Socket实现的.本文会介绍一下基于TCP/IP的Socket编程,并且如何写一个客户端/服务器程序. 餐前甜点 Unix的输入输出(IO)系统遵循Open-Read-Write-Close这样的操作范本.当一个用户进程进行IO操作之前,它需要调用Open来指定并获取待操作文件或设备读取或写入的权限.一旦IO操作对象被打开,那么这个用户进程可以对这个

读懂Java中的Socket编程

Socket,又称为套接字,Socket是计算机网络通信的基本的技术之一.如今大多数基于网络的软件,如浏览器,即时通讯工具甚至是P2P下载都是基于Socket实现的.本文会介绍一下基于TCP/IP的Socket编程,并且如何写一个客户端/服务器程序. 餐前甜点 Unix的输入输出(IO)系统遵循Open-Read-Write-Close这样的操作范本.当一个用户进程进行IO操作之前,它需要调用Open来指定并获取待操作文件或设备读取或写入的权限.一旦IO操作对象被打开,那么这个用户进程可以对这个