现代化专业群建设网站,siren模板wordpress,经典网页设计欣赏,梦幻西游网页微信版什么是Socket
Socket的概念很简单#xff0c;它是网络上运行的两个程序间双向通讯的一端#xff0c;既可以接收请求#xff0c;也可以发送请求#xff0c;利用它可以较为方便地编写网络上数据的传递。
所以简而言之#xff0c;Socket就是进程通信的端点#xff0c;Sock…什么是Socket
Socket的概念很简单它是网络上运行的两个程序间双向通讯的一端既可以接收请求也可以发送请求利用它可以较为方便地编写网络上数据的传递。
所以简而言之Socket就是进程通信的端点Socket之间的连接过程可以分为几步
1、服务器监听
服务器端Socket并不定位具体的客户端Socket而是处于等待连接的状态实时监控网络状态
2、客户端请求
客户端Socket发出连接请求要连接的目标是服务端Socket。为此客户端Socket必须首先描述它要连接的服务端Socket指出服务端Socket的地址和端口号然后就向服务端Socket提出连接请求
3、连接确认
当服务端Socket监听到或者说是接收到客户端Socket的连接请求它就响应客户端Socket的请求建立一个新的线程把服务端Socket的描述发给客户端一旦客户端确认了此描述连接就好了。而服务端Socket继续处于监听状态继续接收其他客户端套接字的连接请求
TCP/IP、HTTP、Socket的区别
这三个概念是比较容易混淆的概念这里尽量解释一下三者之间的区别。
随着计算机网络体系结构的发展OSI七层网络模型诞生了这个模型把开放系统的通信功能划分为七个层次一次完整的通信如下图 每一层都是相互独立的它利用其下一层提供的服务并为其上一层提供服务而与其它层的具体实现无关所谓服务就是下一层向上一层提供的通信功能和层之间的会话约定一般用通信原语实现。上图中从下至上分别给层编号为1~7其中1~4层为下层协议5~7层为上层协议接着回到我们的概念
1、TCP/IP讲的其实是两个东西TCP和IP。IP是一种网络层的协议用于路由选择、网络互连
2、TCP是一种传输层协议用于建立、维护和拆除传送连接在系统之间提供可靠的透明的数据传送
3、HTTP是一种应用层协议提供OSI用户服务例如事物处理程序、文件传送协议和网络管理等其目的最终是为了实现应用进程之间的信息交换
至于Socket它只是TCP/IP网络的API而已Socket接口定义了许多函数用以开发TCP/IP网络上的应用程序组织数据以符合指定的协议。
Socket的两种模式
Socket有两种主要的操作方式面向连接和无连接的。面向连接的Socket操作就像一部电话必须建立一个连接和一人呼叫所有事情在达到时的顺序与它们出发时的顺序一样无连接的Socket操作就像是一个邮件投递没有什么保证多个邮件可能在达到时的顺序与出发时的顺序不一样。
到底使用哪种模式是由应用程序的需要决定的。如果可靠性更重要的话用面向连接的操作会好一些比如文件服务器需要数据的正确性和有序性如果一些数据丢失了系统的有效性将会失去比如一些服务器间歇性地发送一些数据块如果数据丢失了的话服务器并不想要再重新发送一次因为当数据到达的时候它可能已经过时了。确保数据的有序性和正确性需要额外的操作的内存消耗额外的消耗将会降低系统的回应速率。
无连接的操作使用数据报协议。一个数据报是一个独立的单元它包含了所有这次投递的信息就像一个信封它有目的地址和要发送的内容这个模式下的Socket并不需要连接一个目的Socket它只是简单地透出数据报无连接的操作是快速、高效的但是数据安全性不佳。
面向连接的操作使用TCP协议。一个这个模式下的Socket必须在发送数据之前与目的地的Socket取得一个连接一旦连接建立了Socket就可以使用一个流接口打开--读--写--关闭所有发送的信息都会在另一端以同样的顺序被接收。面向连接的操作比无连接的操作效率更低但是数据的安全性更高。
利用Java开发Socket
在Java中面向连接的类有两种形式它们分别是客户端和服务器端先看一下服务器端
public class HelloServer
{
public static void main(String[] args) throws IOException
{
ServerSocket serverSocket null;
try
{
// 实例化一个服务器端的Socket连接
serverSocket new ServerSocket(9999);
}
catch (IOException e)
{
System.err.print(Could not listen on port:9999);
System.exit(1);
}
Socket clientSocket null;
try
{
// 用于接收来自客户端的连接
clientSocket serverSocket.accept();
}
catch (IOException e)
{
System.err.println(Accept failed);
System.exit(1);
}
// 客户端有数据了就向屏幕打印Hello World
System.out.print(Hello World);
clientSocket.close();
serverSocket.close();
}
}
此代码的作用就是构造出服务端Socket并等待来自客户端的消息。当然此时运行代码是没有任何反应的因为服务端在等待客户端的连接。下面看一下客户端代码如何写
public class HelloClient { public static void main(String[] args) throws IOException
{
Socket socket null;
BufferedReader br null;
// 下面这段程序用于将输入输出流和Socket相关联 try { socket new Socket(localhost, 9999);
br new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
catch (UnknownHostException e) { System.err.println(Dont know about host:localhost); System.exit(1); }
catch (IOException e) {
System.err.println(Could not get I/O for the connection); System.exit(1); }
System.out.print(br.readLine());
br.close();
socket.close(); }
}
此时只需要先运行HelloServer再运行HelloClient保证服务器先监听客户端后发送就可以在控制台上看到Hello World了。
改进版本的Socket
上面的Socket演示的效果是服务器端Socket收到了来自客户端Socket的数据但是并没有真正地体现服务器端Socket和客户端Socket的交互下面演示一下利用Socket进行服务器端和客户端的交互首先是服务器端的
public class EchoServer { public static void main(String[] args) throws IOException
{ ServerSocket ss null;
PrintWriter pw null;
BufferedReader br null;
try { // 实例化监听端口 ss new ServerSocket(1111); } catch (IOException e) {
System.err.println(Could not listen on port:1111);
System.exit(1); }
Socket incoming null; while (true) { incoming ss.accept(); pw new PrintWriter(incoming.getOutputStream(), true); // 先将字节流通过InputStreamReader转换为字符流之后将字符流放入缓冲之中 br new BufferedReader(new InputStreamReader(incoming.getInputStream())); // 提示信息
pw.println(Hello!...); pw.println(Enter BYE to exit);
pw.flush();
// 没有异常则不断循环 while (true) { // 只有当用户输入时才返回数据 String str br.readLine(); // 当用户连接断掉时会返回空值null if (str null) {
// 退出循环
break;
}
else
{
// 对用户输入字符串加前缀Echo并将此信息打印到客户端
pw.println(Echo str);
pw.flush();
// 退出命令equalsIgnoreCase()是不区分大小写的
if (BYE.equalsIgnoreCase(str.trim()))
{
break;
}
}
}
// 该close的资源都close掉
pw.close();
br.close();
incoming.close();
ss.close();
}
}
}
接着是客户端的
public class EchoClient
{
public static void main(String[] args) throws IOException
{
Socket socket null;
PrintWriter pw null;
BufferedReader br null;
try
{
socket new Socket(localhost, 1111);
pw new PrintWriter(socket.getOutputStream(), true);
br new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
catch (UnknownHostException e)
{
System.err.println(Dont know abount host:localhost);
System.exit(1);
}
System.out.println(br.readLine());
System.out.println(br.readLine());
BufferedReader stdIn new BufferedReader(new InputStreamReader(System.in));
String userInput;
// 将客户端Socket输入流即服务器端Socket的输出流输出到标准输出上
while ((userInput stdIn.readLine()) ! null)
{
pw.println(userInput);
System.out.println(br.readLine());
}
// 同样的将该关闭的资源给关闭掉
pw.close();
br.close();
socket.close();
}
}
看一下运行结果 这正是我们程序要达到的效果客户端不管输入什么服务器端都给输入拼接上Echo返还给客户端并打印在屏幕上。
服务端多监听
程序写到上面已经基本成型了不过还有一个问题现实情况中一个服务器端的Socket不可能只对应一个客户端的Socket必然一个服务器端的Socket可以接收来自多个客户端的Socket的请求。
解决上述问题的办法就是多线程。大致代码是这样的
public class HandleThread extends Thread
{
private Socket socket;
public HandleThread(Socket socket)
{
this.socket socket;
}
public void run()
{
// Socket处理代码
}
}
public static void main(String[] args) throws IOException
{
ServerSocket serverSocket null;
try
{
// 实例化一个服务器端的Socket连接
serverSocket new ServerSocket(9999);
}
catch (IOException e)
{
System.err.print(Could not listen on port:9999);
System.exit(1);
}
Socket clientSocket null;
try
{
while (true)
{
// 用于接收来自客户端的连接
clientSocket serverSocket.accept();
new HandleThread(clientSocket).start();
}
}
catch (IOException e)
{
System.err.println(Accept failed);
System.exit(1);
}
}
即服务器端启动一个永远运行的线程监听来自客户端的Socket一旦客户端有Socket到来即开启一个新的线程将Socket交给线程处理。
由服务端多监听程序看IO模型
上面的代码用一张图来表示一下这种IO模型 即由一个独立的Acceptor线程负责监听客户端的连接它接收到客户端连接之后为每个客户端创建一个新的线程进行链路处理处理完成之后通过输出流返回应答给客户端线程销毁。这就是典型的一请求一应答通信模型也就是Blocking IO模型即BIO。
该模型最大的问题就是缺乏弹性伸缩能力当客户端并发访问量增大后服务端的线程个数和客户端并发访问数呈1:1的正比关系由于线程是Java虚拟机非常宝贵的系统资源当线程数膨胀之后系统的性能将极具下降随着并发访问量的继续增大系统将会发生线程堆栈溢出、创建新线程失败等问题并最终导致进程宕机或者僵死不能对外提供服务。
在高性能服务器应用领域往往要面向成千上万个客户端的并发连接这种模型显然无法满足高性能、高并发接入的场景。
当然具体问题具体分析BIO性能虽然差但是编程简单如果客户端并发连接数不多周边对接的网元不多服务器的负载也不重那么完全可以使用BIO进行作为服务器的IO模型。 为了让学习变得轻松、高效今天给大家免费分享一套Java教学资源。帮助大家在成为Java架构师的道路上披荆斩棘。需要资料的欢迎加入学习交流群928505736