JAVA学习总结之Socket

HTTP协议能帮助我们解决大部分网络通信的需求,但是HTTP协议规定只能有客户端(浏览器,手机等)主动连接服务器,而服务器不能主动的去连接客户端。但是,在很多即时类应用或者即时类的游戏中,我们不仅需要客户端主动连接服务器,而且还需要服务器也能主动连接客户端,这时Socket就显得非常实用了。

网络基础知识

当我们浏览网页或者发送消息,计算机必须连接到互联网。互联网是连接全球数百万乃至数千万计算机的网络。计算机可以通过互联网服务提供商ISP,使用拨号,DSL,电缆调制器或通过局域网LAN来连接到互联网。
当一台计算机需要与另一台计算机通信的时候,需要知道另一台计算机的地址。互联网协议(IP协议)可以用来唯一地标识互联网上的计算机。IP地址由四段用点隔开的0~255的十进制数组成,例如192.168.0.58。由于这些数字不是很容易记忆,所以经常将它们映射为一个域名,例如www.baidu.com。在互联网上有一个特殊的服务器(DNS)会将域名转换成IP地址。当一台计算机要连接www.baidu.com的服务器时,会首先请求DNS服务器(会先访问本地缓存的映射表),将该域名转换成IP地址,然后用这个IP地址去访问该服务器。
IP协议是在互联网中从一台计算机向另一台计算机传输数据的一种低层协议,数据是以包的形式封装的。两个和IP在一起使用的较高层的协议是传输控制协议(TCP)与用户数据报协议(UDP)。TCP协议能够让两台计算机建立连接并交换数据流。TCP确保数据的传送,也确保数据包以它们发送的顺序正确传送。UDP协议是一宗在IP协议之上的标准的、低开销的、无连接的、主机对主机的协议,UPD协议允许一台计算机的应用程序向另一台计算机上的应用程序发送数据报。TCP协议能够发现丢失的传输信息并重新发送,所以传输过程是无损和可靠的。相对而言,UDP协议不能保证传输没有丢失,也不能保证传输的数据会以一开始的顺序到达对方主机,所以UDP是不可靠的,但是UDP的信息传递更快,如果需要比较快的传递消息,同时不要求信息的可靠性的时候,可以考虑使用UDP。
在Java中支持基于流的通信(TCP)与基于包的通信(UDP),基于流的通信采用的是TCP协议,基于包的通信采用的是UDP协议。

Socket

网络是和Java紧密结合的。Java API提供用于创建套接字Socket的类来便于程序的网络通信
一般而言,一台计算机只有单一的连到网络的物理连接,所有的数据都通过此链接对内、对外送达特定的计算机,这就是端口。网络程序设计中的端口,并非真实的物理存在,而是一种假相的连接装置。
网络中的套接字(Socket)用于将应用程序与端口连接起来,套接字是一个假想的连接装置,就像插座用于连接电器(应用程序)与电线(端口)一样。
java将套接字抽象化为类,如果要使用套接字,只需创建Socket对象即可。

InetAddress类

有时候,你可能会想知道哪些人正连接在服务器上,这时候可以采用这个类来获取客户端的主机名和IP地址。InetAddress类对IP地址建模。
IP地址是IP使用的32位(IPv4)或者128位(IPv6)位无符号数字,它是传输层协议TCP,UDP的基础。InetAddress是Java对IP地址的封装。
InetAddress类没有明显的构造函数。为生成一个InetAddress对象,必须运用一个可用的工厂方法。对于InetAddress,三个方法:getLocalHost()、getByName()以及getAllByName()可以用来创建InetAddress的实例。
- getLocalHost()仅返回本地主机的InetAddress对象。
- getByName()方法返回一个传给它的主机名的InetAddress。
- getAllByName()工厂方法返回代表由一个特殊名称分解的所有地址的InetAddresses类数组。

InetAddress类的常用方法如下

方法返回值说明
getByName(String host)InetAddress获取与Host相对应的InetAddress对象
getHostAddress()String获取InetAddress对象所含的IP地址
getHostName()String获取此IP地址的主机名
getLocalHost()InetAddress获取本地主机的InetAddress对象
/**
 * Created by SunShine on 16/11/2.
 * 使用InetAddress
 */
public class InetAddressDemo {

    public static void main(String[] args) {
        InetAddress inetAddress;
        try {
            inetAddress = InetAddress.getLocalHost();
            String localName = inetAddress.getHostName();
            String localAddress = inetAddress.getHostAddress();
            System.out.println("本机名: " + localName);
            System.out.println("本机地址: " + localAddress);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }
}

//output
//本机名: suandeMacBook-Air.local
//本机地址: 192.168.0.58

ServerSocket类

创建一个服务器,需要创建一个服务器套接字ServceSocket,并把它附加到一个端口上,服务器从这个端口监听连接,端口标志套接字上的TCP服务,端口号的范围从0~65536,0~1024是为特权服务保留的端口号。
java.net包中的ServerSocket类用于表示服务器套接字,其主要功能是等待来自网络上的请求,他可以通过该指定的端口来等待连接的套接字。服务器套接字一次可以与一个套接字连接。如果多台客户机同时提出连接请求,服务器套接字会将请求连接的客户机存入队列中,然后从中取出一个套接字,与服务器新建的套接字连接起来。若请求的连接数大于最大容纳的数,则多出的连接请求被拒绝。队列的默认大小是50.
ServerSocket构造函数声明如下:

//创建非绑定服务器套接字
public ServerSocket() throws IOException
//创建绑定到特定端口的服务器套接字
public ServerSocket(int port) throws IOException
//创建绑定到特定端口的服务器并且设置其最大容量的连接数
public ServerSocket(int port, int backlog) throws IOException
//创建绑定到特定端口,设置其最大容量,同时要绑定到本地IP地址的服务器套接字,大多用于计算机中有多块网卡和多个IP地址的情况,可以明确的用该构造函数去规定ServerSocket在哪块网卡或IP地址上等待客户的连接请求。
public ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException

ServerSocket中的常用方法

//等待客户机的连接,如果连接,则创建一个套接字,acept方法是阻塞式的
public Socket accept() throws IOException
//返回ServerSocket绑定状态
public boolean isBound()
//返回服务器套接字的本地地址
public InetAddress getInetAddress()
//返回服务器套接字的关闭状态
public boolean isClosed()
//关闭服务器套接字
public void close() throws IOException
//将ServerSocket绑定到特定地址(IP地址和端口号)
public void bind(SocketAddress endpoint) throws IOException
public void bind(SocketAddress endpoint, int backlog) throws IOException

调用ServerSocket类的accept()方法会返回一个和客户端Socket对象相连接的Socket对象,服务器端的Socket对象使用getOutputStream()方法获得的输出流将指向客户端Socket对象使用getInputStream()方法获得的那个输入流;同样,服务器端的Socket对象使用getInputStream()方法获得的输入流将指向客户端Socket对象使用getOutputStream()方法获得的那个输出流。也就是说,当服务器想输出流写入信息时,客户端通过相对应的输入流就能读取服务器发送过来的消息,反之亦然。

Socket类

java.net包下的Socket类是封装了网络连接的众多底层操作,我们可以利用Socket去连接服务器主机。
Socket的构造函数声明如下

//创建无连接的Socket
public Socket() 
//创建一个流套接字并将其连接到指定主机上的指定端口号。
Socket(String host, int port) 
//创建一个流套接字并将其连接到指定 IP 地址的指定端口号
Socket(InetAddress address, int port) 
...

得到一个socket之后,就可以利用socket.getInputStream()或者socket.getOutputStream()方法得到输入输出流,这样通过流的方式就可以进行网络通信了。

具体实例

//服务器端
    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(8888);
            Socket socket = serverSocket.accept();
            OutputStream outputStream = socket.getOutputStream();
            DataOutputStream writer = (new DataOutputStream(outputStream));
            writer.writeUTF("Hello World");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
//客户端
    public static void main(String[] args) {
        try {
            Socket socket = new Socket("192.168.199.176", 8888);
            DataInputStream reader = new DataInputStream(socket.getInputStream());
            System.out.println(reader.readUTF());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值