Socket编程学习笔记(一)

来源:互联网 发布:淘宝培训学院 编辑:程序博客网 时间:2024/06/05 15:35

一、什么是Socket编程:

socket是一种最简单的客户机/服务器通信模式。即客户进程向服务器进程发出某种服务请求,服务器响应该请求。如图所示,同常,一个服务器进程会同时为多个客户进程服务,图中的服务器进程B1同时为客户进程A1、A2和B2提供服务。
这里写图片描述
Socket也称为“套接字”,用于描述IP地址和端口,是一个通信链的句柄。应用程序常通过“套接字”向网络发出请求或应答网络请求。它具有以下几个特点:
①Socket是连接运行在网络上的2个程序间的双向通讯的端点。
②网络通讯实际上Socket的通讯。
③通讯的两端都有Socket,数据在两个Socket间通过IO进行传输。

二、使用Socket进行网络通讯的过程

①服务器程序将一个套接字绑定到一个特定的端口,并通过此套接字等待和监听客户端的连接请求。
②客户程序根据服务器程序所在的主机名和端口号发出连接请求。
③如果一切正常,服务器接收连接请求,并获得一个新的绑定到不同端口地址的套接字。
④客户和服务器通过连续读写套接字进行通讯。

这里写图片描述

一般说来Socket编程又分为基于TCP的Socket编程和基于UDP的Socket编程

三、创建TCP服务端/客户端:

创建TCP服务端
①创建一个ServerSocket对象
②调用accept()方法接收客户端请求
③从Socket中获取IO流
④对I/O流进行读写操作,完成与客户端的交互
⑤关闭I/O流和Socket
创建TCP客户端
①创建一个Socket对象
②从Socket中获取IO流
③对IO流进行读写操作,完成与服务端的交互
④关闭IO流和Socket
强调:客户端和服务端进行数据传输时,客户端的输入流对应服务端的输出流,客户端的输出流对应服务端的输入流。

//服务端import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;public class ServerSocketTest1 {    public static void main(String[] args) throws IOException{        ServerSocket serverSocket = new ServerSocket(8080);//将服务端与8080端口绑定        Socket socket = serverSocket.accept();//监听8080端口        System.out.println("ip:"+socket.getInetAddress());        System.out.println("port:"+socket.getPort());        BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));        PrintWriter writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));        String str = null;        while((str = reader.readLine()) != null){            if(str.equals("quit"))//如果接受到的信息是"quit",就退出                break;            System.out.println("get:"+str);            writer.println("server get it");        }        serverSocket.close();        socket.close();        reader.close();        writer.close();    }}

这种写法的问题是如果同时有多个客户端访问,就会出现排队现象,非常影响效率。所以,我们可以使用线程的知识,每次有客户连接,就在线程中处理该请求。修改后的服务端代码如下

//客户端import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;public class ServerSocketTest {    public static void main(String[] args)throws IOException {        ServerSocket serverSocket = new ServerSocket(8080,2);        int flag = 0;        System.out.println("server is ready");        while(true){            Socket socket = serverSocket.accept();            System.out.println("Connect:"+socket.getLocalAddress());            System.err.println("client id:"+(++flag));            System.out.println("Client Port:"+socket.getPort());            handleConnection(socket);//在线程中进行处理        }        //serverSocket.close();    }    private static void handleConnection(Socket socket)throws IOException{        new Thread(new Runnable() {            @Override            public void run() {                try {                    BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));                    PrintWriter writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()),true);                    String str = null;                    while((str = reader.readLine()) != null){                        if(str.equals("quit"))                            break;                        System.out.println("Receive:"+str);                        writer.println("Server received");                    }                    socket.close();                    reader.close();                    writer.close();                } catch (IOException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            }        }).start();    }}

四、基于UDP的Socket编程

1.创建发送端:
①建立DatagramSocket对象,该端点建立时,系统会随机分配一个端口,如果不想随机配置,可以手动指定。
②将数据进行Packet包(DatagramPacket)封装,必须要指定目的地址和端口
③通过Socket服务的Send方法将该包发出
④将Socket关闭
2.创建接收端:
①建立DatagramSocket对象,要监听一个端口
②通过Socket的receive方法将数据存入数据包中
③通过数据包DatagramPacket的方法getData()、getAddress()、getPort()获取包中的指定信息。
④将socket关闭

//接收端import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;public class SocketReceiveTest {    public static void main(String[] args) throws IOException{        DatagramSocket socket = new DatagramSocket(8080);//监听8080端口        byte[] bytes = new byte[100];        DatagramPacket packet1 = new DatagramPacket(bytes, bytes.length);        socket.receive(packet1);        System.out.println(new String(packet1.getData()));        String str = "hello smart";        DatagramPacket packet2 = new DatagramPacket(str.getBytes(), str.length(),                 InetAddress.getByName("localhost"), packet1.getPort());        socket.send(packet2);//接收到消息后返回内容,端口就是发送端的发送端口。        socket.close();    }}


//发送端import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;public class SocketSendTest {    public static void main(String[] args) throws IOException{        DatagramSocket socket = new DatagramSocket();//这里可以不指定本方的发送端口        String str = "hello world";        DatagramPacket packetSend = new DatagramPacket(str.getBytes(), str.length(),                 InetAddress.getByName("localhost"), 8080);//指定发送到localhost的8080端口        System.out.println("send port:"+packetSend.getPort());        socket.send(packetSend);        byte[] bytes = new byte[100];         DatagramPacket packetReceive = new DatagramPacket(bytes, bytes.length);        socket.receive(packetReceive);        System.out.println(new String(packetReceive.getData()));        socket.close();    }}
0 0
原创粉丝点击