Java socket网络编程

1,网络基础和软件编程java

     软件编写人员不须要了解太多的网络知识(基础仍是须要的);软件编写人员主要抓住几点就能够作网络编程;编程

        1,信息传输都是0和1的传输;浏览器

        2,信息传输须要遵守网络协议;(底存的网络协议   和传输格式协议)服务器

        3,抓住传输协议的要点(如  协议的用途   简要协议实现方式)网络

        4,IOapp

    注:有很软件编程人员一般都不知道什么是协议,抓不到协议重点;有些时候在对接的时候问他们使用的什么协议,统一回复tcp/ip协议;这让我非常蛋疼;dom

    补充:OSI(Open System Interconnection)开放式互联协议模型
socket

                        分为7层:1.物理层 2.数据链路层 3.网络层 4.传输层 5.会话层 6.表示层 7.应用层jsp

             TCP/IP协议模型:
tcp

                        分为4层: 1.网络接口层,2.互联网层 3.传输层 4.应用层

            协议都是分层的,咱们经常使用的都是应用层协议;如htpp协议;

            什么是协议?协议规定了咱们在网络传输中的格式样板;

        

2,Java网络编程Socket

   

1,什么是Socket

网络上的两个程序经过一个双向的通信链接实现数据的交换,这个双向链路的一端称为一个SocketSocket一般用来实现客户方和服务方的链接。SocketTCP/IP协议的一个十分流行的编程界面,一个Socket由一个IP地址和一个端口号惟一肯定。

可是,Socket所支持的协议种类也不光TCP/IP一种,所以二者之间是没有必然联系的。在Java环境下,Socket编程主要是指基于TCP/IP协议的网络编程。

2Socket通信的过程

ServerListen(监听)某个端口是否有链接请求,Client端向Server 端发出Connect(链接)请求,Server端向Client端发回Accept(接受)消息。一个链接就创建起来了。Server端和Client 端均可以经过SendWrite等方法与对方通讯。

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

  (1 建立Socket

  (2 打开链接到Socket的输入/出流;

  (3 按照必定的协议对Socket进行读/写操做;

  (4 关闭Socket.(在实际应用中,并未使用到显示的close,虽然不少文章都推荐如此,不过在个人程序中,可能由于程序自己比较简单,要求不高,因此并未形成什么影响。)

3,建立Socket

建立Socket

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

  Socket(InetAddress address, int port);

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

  Socket(String host, int prot);

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

  Socket(SocketImpl impl)

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

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

  ServerSocket(int port);

  ServerSocket(int port, int backlog);

  ServerSocket(int port, int backlog, InetAddress bindAddr)

  其中addresshostport分别是双向链接中另外一方的IP地址、主机名和端 口号,stream指明socket是流socket仍是数据报socketlocalPort表示本地主机的端口号,localAddr bindAddr是本地机器的地址(ServerSocket的主机地址),implsocket的父类,既能够用来建立serverSocket又可 以用来建立Socketcount则表示服务端所能支持的最大链接数。例如:学习视频网 http://www.xxspw.com

  Socket client = new Socket("127.0.01.", 80);

  ServerSocket server = new ServerSocket(80);

  注意,在选择端口时,必须当心。每个端口提供一种特定的服务,只有给出正确的端口,才 能得到相应的服务。0~1023的端口号为系统所保留,例如http服务的端口号为80,telnet服务的端口号为21,ftp服务的端口号为23, 因此咱们在选择端口号时,最好选择一个大于1023的数以防止发生冲突。

  在建立socket时若是发生错误,将产生IOException,在程序中必须对之做出处理。因此在建立SocketServerSocket是必须捕获或抛出例外。

package com.dom.socket;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.ServerSocket;
import java.net.Socket;

public class ServiceDom {

    public static void main(String[] args){
        try {
            ServerSocket server = new ServerSocket(8082);
            Socket socket = server.accept();
            //得到服务端套接字的输入输出流
            Reader reader = new InputStreamReader(socket.getInputStream());  
              char chars[] = new char[64];  
              int len;  
              StringBuilder sb = new StringBuilder();  
              while ((len=reader.read(chars)) != -1) {  
                 sb.append(new String(chars, 0, len));  
              }  
              System.out.println("from client: " + sb);  
              reader.close();  
              socket.close();  
              server.close(); 
        } catch (IOException e) {
            e.printStackTrace();
        }
        
    }
    
}
package com.dom.socket;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.Socket;
import java.net.UnknownHostException;

public class ClientDom {

    public static void main(String [] ags){
        
        try {
            Socket socket = new Socket("127.0.0.1",8082);
            Writer writer = new OutputStreamWriter(socket.getOutputStream());
            writer.write("my socket dom");
            writer.flush();
            writer.close();  
            socket.close(); 

        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }
}

    

使用socket实现http协议传输消息

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;

/**
 * 一个简单的HTTP客户端,发送HTTP请求,模拟浏览器
 * 可打印服务器发送过来的HTTP消息
 */
public class SimpleHttpClient {
    private static String encoding = "GBK";

    public static void main(String[] args) {
        try {
            Socket s = new Socket(InetAddress.getLocalHost(), 8080);
            OutputStreamWriter osw = new OutputStreamWriter(s.getOutputStream());
            StringBuffer sb = new StringBuffer();
            sb.append("GET /HttpStream/gb2312.jsp HTTP/1.1\r\n");
            sb.append("Host: localhost:8088\r\n");
            sb.append("Connection: Keep-Alive\r\n");
            sb.append("\r\n");
            osw.write(sb.toString());
            osw.flush();

            //--输出服务器传回的消息的头信息
            InputStream is = s.getInputStream();
            String line = null;
            int contentLength = 0;//服务器发送回来的消息长度
            // 读取全部服务器发送过来的请求参数头部信息
            do {
                line = readLine(is, 0);
                //若是有Content-Length消息头时取出
                if (line.startsWith("Content-Length")) {
                    contentLength = Integer.parseInt(line.split(":")[1].trim());
                }
                //打印请求部信息
                System.out.print(line);
                //若是遇到了一个单独的回车换行,则表示请求头结束
            } while (!line.equals("\r\n"));

            //--输消息的体
            System.out.print(readLine(is, contentLength));

            //关闭流
            is.close();

        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*
     * 这里咱们本身模拟读取一行,由于若是使用API中的BufferedReader时,它是读取到一个回车换行后
     * 才返回,不然若是没有读取,则一直阻塞,直接服务器超时自动关闭为止,若是此时还使用BufferedReader
     * 来读时,由于读到最后一行时,最后一行后不会有回车换行符,因此就会等待。若是使用服务器发送回来的
     * 消息头里的Content-Length来截取消息体,这样就不会阻塞
     * 
     * contentLe 参数 若是为0时,表示读头,读时咱们仍是一行一行的返回;若是不为0,表示读消息体,
     * 时咱们根据消息体的长度来读完消息体后,客户端自动关闭流,这样不用先到服务器超时来关闭。
     */
    private static String readLine(InputStream is, int contentLe) throws IOException {
        ArrayList lineByteList = new ArrayList();
        byte readByte;
        int total = 0;
        if (contentLe != 0) {
            do {
                readByte = (byte) is.read();
                lineByteList.add(Byte.valueOf(readByte));
                total++;
            } while (total < contentLe);//消息体读还未读完
        } else {
            do {
                readByte = (byte) is.read();
                lineByteList.add(Byte.valueOf(readByte));
            } while (readByte != 10);
        }

        byte[] tmpByteArr = new byte[lineByteList.size()];
        for (int i = 0; i < lineByteList.size(); i++) {
            tmpByteArr[i] = ((Byte) lineByteList.get(i)).byteValue();
        }
        lineByteList.clear();

        return new String(tmpByteArr, encoding);
    }
}

    上面都是采用的是io;由于NIO的缘故  这些代码都不是本身写的;后面准备本身写NIO的实现;(就这一点东东就花了了我一天时间   真心伤不起呀;基础   基础  基础夯实真的很重要)   在此记录以备后用

相关文章
相关标签/搜索