黑马程序员----JAVA Socket编程

---------------------- android培训 、 java培训 、 期待与您交流! ------------------

1、Socket简介:

80年代初,美国政府的高级研究工程机构(ARPA)给加利福尼亚大学Berkeley分校提供了资金,让他们在UNIX操作系统下实现TCP/IP协议。在这个项目中,研究人员为TCP/IP网络通信开发了一个API(应用程序接口)。这个API称为Socket接口(套接字)。今天,SOCKET接口是TCP/IP网络最为通用的API,也是在INTERNET上进行应用开发最为通用的API

90年代初,由Microsoft联合了其他几家公司共同制定了一套WINDOWS下的网络编程接口,即WindowsSockets规范。它是BerkeleySockets的重要扩充,主要是增加了一些异步函数,并增加了符合Windows消息驱动特性的网络事件异步选择机制。WINDOWSSOCKETS规范是一套开放的、支持多种协议的Windows下的网络编程接口。从1991年的1.0版到1995年的2.0.8版,经过不断完善并在IntelMicrosoftSunSGIInformixNovell等公司的全力支持下,已成为Windows网络编程的事实上的标准。目前,在实际应用中的WINDOWSSOKCETS规范主要有1.1版和2.0版。两者的最重要区别是1.1版只支持TCP/IP协议,而2.0版可以支持多协议。2.0版有良好的向后兼容性,任何使用1.1版的源代码,二进制文件,应用程序都可以不加修改地在2.0规范下使用。

SOCKET实际在计算机中提供了一个通信端口,可以通过这个端口与任何一个具有SOCKET接口的计算机通信。应用程序在网络上传输,接收的信息都通过这个SOCKET接口来实现。在应用开发中就像使用文件句柄一样,可以对SOCKET句柄进行读,写操作。

2、Socket的机制:

我们可以简单的把Socket理解为一个可以连通网络上不同计算机程序之间的管道,把一堆数据从管道的A端扔进去,则会从管道的B端(也许同时还可以从CDEF……端冒出来)。管道的端口由两个因素来唯一确认,即机器的IP地址和程序所使用的端口号。IP地址的含义所有人都知道,所谓端口号就是程序员指定的一个数字,许多著名的木马程序成天在网络上扫描不同的端口号就是为了获取一个可以连通的端口从而进行破坏。比较著名的端口号有http80端口和ftp21端口。当然,建议大家自己写程序不要使用太小的端口号,它们一般被系统占用了,也不要使用一些著名的端口,一般来说使用1000~5000之内的端口比较好。

Socket可以支持数据的发送和接收,它会定义一种称为套接字的变量,发送数据时必须首先创建套接字.

3、Socket、 TCP/IP:

Socket则是对TCP/IP协议的封装和应用(程序员层面上)。

TPC/IP协议是传输层协议,主要解决数据如何在网络中传输。

Socket的出现只是使得程序员更方便地使用TCP/IP协议栈而已,是对TCP/IP协议的抽象。


4、Socket通信的原理:

套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。

(1)、服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。

(2)、客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。

(3)、连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。

而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。


开发时分为服务器端跟客户端。

服务器端的步骤如下:

(1)建立服务器端的Socket,确定监听的端口号,开始侦听整个网络中的连接请求。

(2)当检测到来自客户端的连接请求时,向客户端发送收到连接请求的信息,并建立与客户端之间的连接。

(3)当完成通信后,服务器关闭与客户端的Socket连接。

客户端的步骤如下:

(1)建立客户端的Socket,确定要连接的服务器的主机名和端口。

(2)发送连接请求到服务器,并等待服务器的回馈信息。

(3)连接成功后,与服务器进行数据的交互。

(4)数据处理完毕后,关闭自身的Socket连接。

5、Socket开发小例:

//客户端:

  

    import java.io.*;
    import java.net.*;
    public class Client {  
       
       public static void main(String args[]) throws Exception {  
          //为了简单起见,所有的异常都直接往外抛  
         String host = "127.0.0.1";  //要连接的服务端IP地址  
         int port = 4999;   //要连接的服务端对应的监听端口  
         //与服务端建立连接  
         Socket client = new Socket(host, port);  
          //建立连接后就可以往服务端写数据了  
         Writer writer = new OutputStreamWriter(client.getOutputStream(), "GBK");  
          writer.write("你好,服务端。");  
          writer.write("eof\n");  
          writer.flush();  
          //写完以后进行读操作  
         BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream(),"UTF-8"));  
          //设置超时间为10秒  
         client.setSoTimeout(10*1000);  
          StringBuffer sb = new StringBuffer();  
          String temp;  
          int index;  
          try {  
             while ((temp=br.readLine()) != null) {  
                if ((index = temp.indexOf("eof")) != -1) {  
                    sb.append(temp.substring(0, index));  
                    break;  
                }  
                sb.append(temp);  
             }  
          } catch (SocketTimeoutException e) {  
             System.out.println("数据读取超时。");  
          }  
          System.out.println("服务端: " + sb);  
          writer.close();  
          br.close();  
          client.close();  
       }  
    }  


//服务器端:

   

    import java.io.*;
    import java.net.*;
    public class Server {  
       
       public static void main(String args[]) throws IOException {  
          //为了简单起见,所有的异常信息都往外抛  
          int port = 4999;  
          //定义一个ServerSocket监听在端口4999上  
          ServerSocket server = new ServerSocket(port);  
          while (true) {  
             //server尝试接收其他Socket的连接请求,server的accept方法是阻塞式的  
             Socket socket = server.accept();  
             //每接收到一个Socket就建立一个新的线程来处理它  
             new Thread(new Task(socket)).start();  
          }  
       }  
         
       /**
        * 用来处理Socket请求的
        */  
       static class Task implements Runnable {  
       
          private Socket socket;  
            
          public Task(Socket socket) {  
             this.socket = socket;  
          }  
            
          public void run() {  
             try {  
                handleSocket();  
             } catch (Exception e) {  
                e.printStackTrace();  
             }  
          }  
            
          /**
           * 跟客户端Socket进行通信
          * @throws Exception
           */  
          private void handleSocket() throws Exception {  
             BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "GBK"));  
             StringBuilder sb = new StringBuilder();  
             String temp;  
             int index;  
             while ((temp=br.readLine()) != null) {  
                System.out.println(temp);  
                if ((index = temp.indexOf("eof")) != -1) {//遇到eof时就结束接收  
                 sb.append(temp.substring(0, index));  
                    break;  
                }  
                sb.append(temp);  
             }  
             System.out.println("客户端: " + sb);  
             //读完后写一句  
           Writer writer = new OutputStreamWriter(socket.getOutputStream(), "UTF-8");  
             writer.write("你好,客户端。");  
             writer.write("eof\n");  
             writer.flush();  
             writer.close();  
             br.close();  
             socket.close();  
          }  
       }  
    } 



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值