Socket编程学习笔记(一)

一、什么是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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值