Socket学习笔记 仅用于条理知识

今儿想看看进程间的通讯,信号量,PV操作什么的好TM费脑,索性就看其中的网络间进程通讯---socket编程,对这部分一直想敲敲代码,一直想不起来,因为不懂的太多了,每时每刻都是学不完的东西,今儿终于破个头儿。

本地的进程间通讯(IPC)有很多方式:

管道,,消息队列,信箱

同步(互斥量,条件变量,读写锁,信号量)

共享内存(匿名,具名)

在本地这些可以通过进程PID来唯一标示一个进程,网络编程中行不通,TCP/IP可以帮我们解决这个问题,网络层的“ip”可以唯一标示网络中的一台主机,而传输层的“协议+端口”可以唯一标示一台主机上的一个应用程序

使用TCP/IP协议的应用程序一般都是:UNIX BSD的套接字(socket)和UNIX System V的TLI(基本淘汰),所以现在几乎都是socket

参考文章:http://haohaoxuexi.iteye.com/blog/1979837      按着这个写了写,感觉很不错,层层深入   仅作为自己的学习笔记   理一理 条理一下体系

1 客户端写 服务器读

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

/**
 * Created by albert.bai on 2014/10/29.
 */
public class Server {
    public static void main(String[] args) throws IOException {//所有异常都往外抛,为了方便而已
        int port = 8899;
        //定义一个ServerSocket监听在8899上 1024一下的端口不要用
        ServerSocket serverSocket = new ServerSocket(port);
        //尝试接受其他Socket的连接请求,server的accept方法应该是阻塞的
        Socket socket = serverSocket.accept();
        //跟客户端建立好连接后,我们就可以获取socket的InputStream,并从中读取客户端发过来的信息了
        Reader reader = new InputStreamReader(socket.getInputStream());
        char chars[] = new char[64];
        int length;
        StringBuffer stringBuffer = new StringBuffer();
        while ((length=reader.read(chars))!=-1) {
            stringBuffer.append(chars,0,length);
        }
        System.out.println("from client:"+stringBuffer);
        reader.close();
        socket.close();
        serverSocket.close();
        }
    }

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

/**
 * Created by albert.bai on 2014/10/29.
 */
public class Client {
    public static void main(String[] args) throws Exception {
        String host ="127.0.0.1";//要连接的服务端IP  打开C:\Windows\System32\drivers\etc\hosts去看 原谅我还在用windows  囧
        int port =8899;//要连接的服务器端对应的监听端口
        Socket client = new Socket(host,port);//与服务器建立连接
        Writer writer = new OutputStreamWriter(client.getOutputStream());
        writer.write("Hello Server");
        writer.flush();//写完后记得冲过去  如果写操作后对应的不是对应着输出流的关闭,而是其他阻塞式的操作,要flush一下,这样server才能接到数据
        writer.close();
        client.close();

    }
}
切记关闭IO流和socket

2 server和client 同时读和写

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * Created by albert.bai on 2014/10/29.
 */
public class Server {
    public static void main(String[] args) throws IOException {//所有异常都往外抛,为了方便而已
        int port = 8899;
        //定义一个ServerSocket监听在8899上 1024一下的端口不要用
        ServerSocket serverSocket = new ServerSocket(port);
        //尝试接受其他Socket的连接请求,server的accept方法应该是阻塞的
        Socket socket = serverSocket.accept();
        //跟客户端建立好连接后,我们就可以获取socket的InputStream,并从中读取客户端发过来的信息了
        Reader reader = new InputStreamReader(socket.getInputStream());
        char chars[] = new char[64];
        int length;
        StringBuffer stringBuffer = new StringBuffer();
        while ((length=reader.read(chars))!=-1) {
            stringBuffer.append(chars,0,length);
        }
        System.out.println("from client:"+stringBuffer);
        //读完了 写一句
        Writer writer = new OutputStreamWriter(socket.getOutputStream());
        writer.write("Hello Client");
        writer.flush();
        writer.close();
        reader.close();
        socket.close();
        serverSocket.close();
        }
    }

上述代码在获取客户端发过来的信息后,发送一句信息给客户端,但也许永远都发不出去,除非客户端的socket关闭,因为接收信息是个阻塞式操作,这时length已经没什么效力了 因为永远接不到消息,这时我们用一个客户端发来的“eof”作为信息结束的标志来跳出循环

import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.net.Socket;

/**
 * Created by albert.bai on 2014/10/29.
 */
public class Client {
    public static void main(String[] args) throws Exception {
        String host ="127.0.0.1";//要连接的服务端IP  打开C:\Windows\System32\drivers\etc\hosts去看 原谅我还在用windows  囧
        int port =8899;//要连接的服务器端对应的监听端口
        Socket client = new Socket(host,port);//与服务器建立连接
        Writer writer = new OutputStreamWriter(client.getOutputStream());
        writer.write("Hello Server");
        writer.write("eof");
        writer.flush();//写完后记得冲过去  如果写操作后对应的不是对应着输出流的关闭,而是其他阻塞式的操作,要flush一下,这样server才能接到数据
        //写完了读一个
        Reader reader = new InputStreamReader(client.getInputStream());
        char[] chars = new char[64];
        int length;
        StringBuffer sb = new StringBuffer();
        String temp;
        int index;
        while ((length =reader.read(chars))!=-1) {
            temp = new String(chars,0,length);
            if ((index = temp.indexOf("eof"))!=-1) {
                sb.append(temp.substring(0,index));
                break;
            }
            sb.append(new String(chars,0,length));
        }
        writer.close();
        client.close();

    }
}

修改server代码

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * Created by albert.bai on 2014/10/29.
 */
public class Server {
    public static void main(String[] args) throws IOException {//所有异常都往外抛,为了方便而已
        int port = 8899;
        //定义一个ServerSocket监听在8899上 1024一下的端口不要用
        ServerSocket serverSocket = new ServerSocket(port);
        //尝试接受其他Socket的连接请求,server的accept方法应该是阻塞的
        Socket socket = serverSocket.accept();
        //跟客户端建立好连接后,我们就可以获取socket的InputStream,并从中读取客户端发过来的信息了
        Reader reader = new InputStreamReader(socket.getInputStream());
        char chars[] = new char[64];
        String temp;
        int length;
        int index;
        StringBuffer stringBuffer = new StringBuffer();
        while ((length=reader.read(chars))!=-1) {
            temp = new String(chars,0,length);
            if((index = temp.indexOf("eof"))!=-1) {//遇到eof结束
                stringBuffer.append(temp.substring(0,index));
                break;
            }
            stringBuffer.append(temp);
        }
        System.out.println("from client:"+stringBuffer);
        //读完了 写一句
        Writer writer = new OutputStreamWriter(socket.getOutputStream());
        writer.write("Hello Client");
        writer.write("eof");
        writer.flush();
        writer.close();
        reader.close();
        socket.close();
        serverSocket.close();
        }
    }

3 多个client 连接一个server

上面的代码在接受一个server请求后就不再接受其他请求,这样多不符合程序员高端,大气,上档次的气质  改!

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * Created by albert.bai on 2014/10/29.
 */
public class Server {
    public static void main(String[] args) throws IOException {//所有异常都往外抛,为了方便而已
        int port = 8899;
        //定义一个ServerSocket监听在8899上 1024一下的端口不要用
        ServerSocket serverSocket = new ServerSocket(port);
        while (true) {
            //尝试接受其他Socket的连接请求,server的accept方法应该是阻塞的
            Socket socket = serverSocket.accept();
            //跟客户端建立好连接后,我们就可以获取socket的InputStream,并从中读取客户端发过来的信息了
            Reader reader = new InputStreamReader(socket.getInputStream());
            char chars[] = new char[64];
            String temp;
            int length;
            int index;
            StringBuffer stringBuffer = new StringBuffer();
            while ((length = reader.read(chars)) != -1) {
                temp = new String(chars, 0, length);
                if ((index = temp.indexOf("eof")) != -1) {//遇到eof结束
                    stringBuffer.append(temp.substring(0, index));
                    break;
                }
                stringBuffer.append(temp);
            }
            System.out.println("from client:" + stringBuffer);
            //读完了 写一句
            Writer writer = new OutputStreamWriter(socket.getOutputStream());
            writer.write("Hello Client");
            writer.write("eof");
            writer.flush();
            writer.close();
            reader.close();
            socket.close();
        }
    }
    }
设置一个死循环,这样在处理完一个请求后就可以处理下一个请求,但这样和client请求时同步进行的,当请求过多时就会丢掉一些请求,还是不符合我们的气质啊  改!!

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * Created by albert.bai on 2014/10/29.
 */
public class Server {
    public static void main(String[] args) throws IOException {//所有异常都往外抛,为了方便而已
        int port = 8899;
        //定义一个ServerSocket监听在8899上 1024一下的端口不要用
        ServerSocket serverSocket = new ServerSocket(port);
        while (true) {
            //尝试接受其他Socket的连接请求,server的accept方法应该是阻塞的
            Socket socket = serverSocket.accept();
            new Thread(new Task(socket)).start();
        }
    }

    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();
            }
        }

        private void handleSocket() throws Exception {
            //跟客户端建立好连接后,我们就可以获取socket的InputStream,并从中读取客户端发过来的信息了
            Reader reader = new InputStreamReader(socket.getInputStream());
            char chars[] = new char[64];
            String temp;
            int length;
            int index;
            StringBuffer stringBuffer = new StringBuffer();
            while ((length = reader.read(chars)) != -1) {
                temp = new String(chars, 0, length);
                if ((index = temp.indexOf("eof")) != -1) {//遇到eof结束
                    stringBuffer.append(temp.substring(0, index));
                    break;
                }
                stringBuffer.append(temp);
            }
            System.out.println("from client:" + stringBuffer);
            //读完了 写一句
            Writer writer = new OutputStreamWriter(socket.getOutputStream());
            writer.write("Hello Client");
            writer.write("eof");
            writer.flush();
            writer.close();
            reader.close();
            socket.close();

        }
    }


}

这样我们就可以采用异步的方式处理请求了,在每个请求发过来后开启一个线程去跑就好了    现在我们换成BufferReader来一次读一行数据

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * Created by albert.bai on 2014/10/29.
 */
public class Server {
    public static void main(String[] args) throws IOException {//所有异常都往外抛,为了方便而已
        int port = 8899;
        //定义一个ServerSocket监听在8899上 1024一下的端口不要用
        ServerSocket serverSocket = new ServerSocket(port);
        while (true) {
            //尝试接受其他Socket的连接请求,server的accept方法应该是阻塞的
            Socket socket = serverSocket.accept();
            new Thread(new Task(socket)).start();
        }
    }

    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();
            }
        }

        private void handleSocket() throws Exception {
            //跟客户端建立好连接后,我们就可以获取socket的InputStream,并从中读取客户端发过来的信息了
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String temp;
            int index;
            StringBuffer stringBuffer = new StringBuffer();
            while ((temp = bufferedReader.readLine())!=null) {
                System.out.println(temp);
                if ((index = temp.indexOf("eof")) != -1) {//遇到eof结束
                    stringBuffer.append(temp.substring(0, index));
                    break;
                }
                stringBuffer.append(temp);
            }
            System.out.println("from client:" + stringBuffer);
            //读完了 写一句
            Writer writer = new OutputStreamWriter(socket.getOutputStream());
            writer.write("Hello Client");
            writer.write("eof\n"); //换行符啊  上面可是readline啊
            writer.flush();
            writer.close();
            bufferedReader.close();
            socket.close();

        }
    }


}

readline在读到换行符或者对应流的结束符才会认为我已经读了一行了  切记flush一下  这样才会从缓冲区里写入

对应的client

import java.io.*;
import java.net.Socket;

/**
 * Created by albert.bai on 2014/10/29.
 */
public class Client {
    public static void main(String[] args) throws Exception {
        String host ="127.0.0.1";//要连接的服务端IP  打开C:\Windows\System32\drivers\etc\hosts去看 原谅我还在用windows  囧
        int port =8899;//要连接的服务器端对应的监听端口
        Socket client = new Socket(host,port);//与服务器建立连接
        Writer writer = new OutputStreamWriter(client.getOutputStream());
        writer.write("Hello Server");
        writer.write("eof\n");
        writer.flush();//写完后记得冲过去  如果写操作后对应的不是对应着输出流的关闭,而是其他阻塞式的操作,要flush一下,这样server才能接到数据
        //写完了读一个
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(client.getInputStream()));

        StringBuffer sb = new StringBuffer();
        String temp;
        int index;
        while ((temp =bufferedReader.readLine())!=null) {
            
            if ((index = temp.indexOf("eof"))!=-1) {
                sb.append(temp.substring(0,index));
                break;
            }
            sb.append(temp);
        }
        writer.close();
        bufferedReader.close();
        client.close();

    }
}

4 设置Time-out

import java.io.*;
import java.net.Socket;
import java.net.SocketTimeoutException;

/**
 * Created by albert.bai on 2014/10/29.
 */
public class Client {
    public static void main(String[] args) throws Exception {
        String host ="127.0.0.1";//要连接的服务端IP  打开C:\Windows\System32\drivers\etc\hosts去看 原谅我还在用windows  囧
        int port =8899;//要连接的服务器端对应的监听端口
        Socket client = new Socket(host,port);//与服务器建立连接
        Writer writer = new OutputStreamWriter(client.getOutputStream());
        writer.write("Hello Server");
        writer.write("eof\n");
        writer.flush();//写完后记得冲过去  如果写操作后对应的不是对应着输出流的关闭,而是其他阻塞式的操作,要flush一下,这样server才能接到数据
        //写完了读一个
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(client.getInputStream()));
        client.setSoTimeout(10*1000);//防止一直没有读到数据 超时抛出异常 单位毫秒
        StringBuffer sb = new StringBuffer();
        String temp;
        int index;
        try {
            while ((temp = bufferedReader.readLine()) != null) {

                if ((index = temp.indexOf("eof")) != -1) {
                    sb.append(temp.substring(0, index));
                    break;
                }
                sb.append(temp);
            }
        }catch (SocketTimeoutException e) {
            System.out.println("数据读取超时");
            e.printStackTrace();
        }
        writer.close();
        bufferedReader.close();
        client.close();

    }
}

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;

/**
 * Created by albert.bai on 2014/10/29.
 */
public class Server {
    public static void main(String[] args) throws IOException {//所有异常都往外抛,为了方便而已
        int port = 8899;
        //定义一个ServerSocket监听在8899上 1024一下的端口不要用
        ServerSocket serverSocket = new ServerSocket(port);
        while (true) {
            //尝试接受其他Socket的连接请求,server的accept方法应该是阻塞的
            Socket socket = serverSocket.accept();
            new Thread(new Task(socket)).start();
        }
    }

    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();
            }
        }

        private void handleSocket() throws Exception {
            //跟客户端建立好连接后,我们就可以获取socket的InputStream,并从中读取客户端发过来的信息了
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String temp;
            int index;
            StringBuffer stringBuffer = new StringBuffer();
            socket.setSoTimeout(10*1000);
            try {
                while ((temp = bufferedReader.readLine()) != null) {
                    System.out.println(temp);
                    if ((index = temp.indexOf("eof")) != -1) {//遇到eof结束
                        stringBuffer.append(temp.substring(0, index));
                        break;
                    }
                    stringBuffer.append(temp);
                }
                System.out.println("from client:" + stringBuffer);
            }catch (SocketTimeoutException e) {
                System.out.println("数据读取超时");
                e.printStackTrace();
            }
            //读完了 写一句
            Writer writer = new OutputStreamWriter(socket.getOutputStream());
            writer.write("Hello Client");
            writer.write("eof\n"); //换行符啊  上面可是readline啊
            writer.flush();
            writer.close();
            bufferedReader.close();
            socket.close();

        }
    }


}


满满的成就感


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值