基于Java的Scoket编程

目录
  • 一,网络编程中两个主要的问题
  • 二,两类传输协议:TCP和UDP
    • TCP和UDP的区别
  • 三,基于Socket的java网络编程
    • 1、什么是Socket
    • 2、Socket通讯的过程
    • 3、创建Socket
  • 代码演示
    • 例:基于TCP的数据传输,传递字符串
    • 例:基于TCP的数据传输,传输对象
    • 例:基于多线程的通讯请求,多客户端访问服务器
    • 例:基于UDP的数据传递

一,网络编程中两个主要的问题

一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输。

在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的路由,由IP地址可以唯一地确定Internet上的一台主机。

而TCP层则提供面向应用的可靠(tcp)的或非可靠(UDP)的数据传输机制,这是网络编程的主要对象,一般不需要关心IP层是如何处理数据的。

目前较为流行的网络编程模型是客户机/服务器(C/S)结构。 即通信双方一方作为服务器等待客户提出请求并予以响应。客户则在需要服务时向服务器提 出申请。服务器一般作为守护进程始终运行,监听网络端口,一旦有客 户请求,就会启动一个服务进程来响应该客户,同时自己继续监听服务端口,使后来的客户也 能及时得到服务。

二,两类传输协议:TCP和UDP

TCP是Tranfer Control Protocol的 简 称,是一种面向连接的保证可靠传输的协议。通过TCP协议传输,得到的是一个顺序的无差错的数据流。发送方和接收方的成对的两个socket之间必须 建 立连接,以便在TCP协议的基础上进行通信,当一个socket(通常都是server socket)等待建立连接时,另一个socket可以要求进行连接,一旦这两个socket连接起来,它们就可以进行双向数据传输,双方都可以进行发 送 或接收操作。

UDP是User Datagram Protocol的简称,是一种无连接的协议,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,它在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。

TCP和UDP的区别

UDP:

  • 1、每个数据报中都给出了完整的地址信息,因此无需要建立发送方和接收方的连接。
  • 2、UDP传输数据时是有大小限制的,每个被传输的数据报必须限定在64KB之内。
  • 3、UDP是一个不可靠的协议,发送方所发送的数据报并不一定以相同的次序到达接收方

TCP:

  • 1、面向连接的协议,在socket之间进行数据传输之前必然要建立连接,所以在TCP中需要连接时间。
  • 2、TCP传输数据大小限制,一旦连接建立起来,双方的socket就可以按统一的格式传输大的数据。
  • 3、TCP是一个可靠的协议,它确保接收方完全正确地获取发送方所发送的全部数据。

应用:

  • 1、TCP在网络通信上有极强的生命力,例如远程连接(Telnet)和文件传输(FTP)都需要不定长度的数据被可靠地传输。但是可靠的传输是要付出代价的,对数据内容正确性的检验必然占用计算机的处理时间和网络的带宽,因此TCP传输的效率不如UDP高。
  • 2、UDP操作简单,而且仅需要较少的监护,因此通常用于局域网高可靠性的分散系统中client/server应用程序。例如视频会议系统,并不要求音频视频数据绝对的正确,只要保证连贯性就可以了,这种情况下显然使用UDP会更合理一些。

三,基于Socket的java网络编程

1、什么是Socket

网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个Socket。Socket通常用来实现客户方和服务方的连接。Socket是TCP/IP协议的一个十分流行的编程界面,一个Socket由一个IP地址和一个端口号唯一确定。

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

2、Socket通讯的过程

Server端Listen(监听)某个端口是否有连接请 求,Client端向Server 端发出Connect(连接)请求,Server端向Client端发回Accept(接受)消息。一个连接就建立起 来了。Server端和Client 端都可以通过Send,Write等方法与对方通信。

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

  • (1) 创建Socket;
  • (2) 打开连接到Socket的输入/出流;
  • (3) 按照一定的协议对Socket进行读/写操作;
  • (4) 关闭Socket.(在实际应用中,并未使用到显示的close,虽然很多文章都推荐如此,不过在我的程序中,可能因为程序本身比较简单,要求不高,所以并未造成什么影响。)

3、创建Socket

创建Socket

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

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)

其中address、host和port分别是双向连接中 另一方的IP地址、主机名和端 口号,stream指明socket是流socket还是数据报socket,localPort表示本地主机的端口 号,localAddr和 bindAddr是本地机器的地址(ServerSocket的主机地址),impl是socket的父类,既可以用来创建 serverSocket又可 以用来创建Socket。count则表示服务端所能支持的最大连接数。例如:我们 https://www.jb51.net

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

ServerSocket server = new ServerSocket(80);

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

在创建socket时如果发生错误,将产生IOException,在程序中必须对之作出处理。所以在创建Socket或ServerSocket是必须捕获或抛出例外。

代码演示

例:基于TCP的数据传输,传递字符串

服务器端:

public class SocketServer {
    public static void main(String[] args) {
        try {
            /*
             * 1、创建serverScoket对象
             * 2、调用accept()方法开启监听
             * 3、获取文件流(输出流或输入流)
             * 4、执行读写操作
             * 5、关闭流
             * 6、关闭serversocket。
             */
            ServerSocket server = new ServerSocket(8888);
            System.out.println("服务器已经启动!");
            // 接收客户端发送的信息
            Socket socket = server.accept();

            InputStream is = socket.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));

            String info = null;
            while ((info = br.readLine()) != null) {
                System.out.println(info);
            }

            // 向客户端写入信息
            OutputStream os = socket.getOutputStream();
            String str = "欢迎登陆到server服务器!";
            os.write(str.getBytes());

            // 关闭文件流
            os.close();
            br.close();
            is.close();
            socket.close();
            server.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

客户端:

public class SocketClient {
    public static void main(String[] args) {

        try {
            /*
             * 1、创建socket,指定服务器的地址和端口号
             * 2、创建文件流
             * 3、执行读取或者写入操作
             * 4、关闭文件流
             * 5、关闭socket
             */
            System.out.println("客户端已启动!");
            Socket socket = new Socket("localhost", 8888);

            OutputStream os = socket.getOutputStream();
            String msg = "用户名:张三  密码:123123";
            os.write(msg.getBytes());
            socket.shutdownOutput();

            //获取服务器响应信息
            InputStream is = socket.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));

            String info = null;
            while ((info = br.readLine()) != null) {
                System.out.println(info);
            }

            //关闭资源
            br.close();
            os.close();
            is.close();

            socket.close();

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

例:基于TCP的数据传输,传输对象

服务器端:

public class SocketServer {
    public static void main(String[] args) {
        try {
            /*
             * 1、创建serverScoket对象
             * 2、调用accept()方法开启监听
             * 3、获取文件流(输出流或输入流)
             * 4、执行读写操作
             * 5、关闭流
             * 6、关闭serversocket。
             */
            ServerSocket server = new ServerSocket(8888);
            System.out.println("服务器已经启动!");
            // 接收客户端发送的信息
            Socket socket = server.accept();

            InputStream is = socket.getInputStream();
            // 执行反序列化
            ObjectInputStream ois = new ObjectInputStream(is);
            Student stu = (Student) ois.readObject();
            stu.Show();

            // 向客户端写入信息
            OutputStream os = socket.getOutputStream();
            String str = "欢迎登陆到server服务器!";
            os.write(str.getBytes());

            // 关闭文件流
            ois.close();
            os.close();
            is.close();
            socket.close();
            server.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

客户端:

public class SocketClient {
    public static void main(String[] args) {

        try {
            /*
             * 1、创建socket,指定服务器的地址和端口号
             * 2、创建文件流
             * 3、执行读取或者写入操作
             * 4、关闭文件流
             * 5、关闭socket
             */
            System.out.println("客户端已启动!");
            Socket socket = new Socket("localhost", 8888);

            OutputStream os = socket.getOutputStream();
            //创建对象
            Student stu = new Student();
            stu.setName("张三");
            stu.setPwd("123123");

            //执行序列化操作
            ObjectOutputStream oos = new ObjectOutputStream(os);
            oos.writeObject(stu);
            socket.shutdownOutput();

            //获取服务器响应信息
            InputStream is = socket.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));

            String info = null;
            while ((info = br.readLine()) != null) {
                System.out.println(info);
            }

            //关闭资源
            br.close();
            is.close();
            oos.close();
            os.close();
            socket.close();

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

例:基于多线程的通讯请求,多客户端访问服务器

服务器端:

public class SocketServer {
    public static void main(String[] args) {
        try {
            /*
             * 1、创建serverScoket对象 2、调用accept()方法开启监听 3、获取文件流(输出流或输入流) 4、执行读写操作
             * 5、关闭流 6、关闭serversocket。
             */
            ServerSocket server = new ServerSocket(8888);
            System.out.println("服务器已经启动!");
            // 接收客户端发送的信息
            while (true) {
                //阻塞会让程序停止
                Socket socket = server.accept();
                ServerThread st = new ServerThread(socket);
                st.start();
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

线程类:

public class ServerThread extends Thread {
    private Socket socket;

    public ServerThread(Socket socket) {
        this.socket = socket;
    }

    public void run() {
        InputStream is;
        try {
            is = socket.getInputStream();

            // 执行反序列化
            ObjectInputStream ois = new ObjectInputStream(is);
            Student stu = (Student) ois.readObject();
            stu.Show();

            // 向客户端写入信息
            OutputStream os = socket.getOutputStream();
            String str = "欢迎登陆到server服务器!";
            os.write(str.getBytes());

            // 关闭文件流
            os.close();
            ois.close();
            is.close();
            socket.close();

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

    }
}

客户端:

public class SocketClient {
    public static void main(String[] args) {

        try {
            /*
             * 1、创建socket,指定服务器的地址和端口号
             * 2、创建文件流
             * 3、执行读取或者写入操作
             * 4、关闭文件流
             * 5、关闭socket
             */
            System.out.println("客户端已启动!");
            Socket socket = new Socket("localhost", 8888);

            OutputStream os = socket.getOutputStream();
            //创建对象
            Student stu = new Student();
            stu.setName("张三");
            stu.setPwd("123123");

            //执行序列化操作
            ObjectOutputStream oos = new ObjectOutputStream(os);
            oos.writeObject(stu);
            socket.shutdownOutput();

            //获取服务器响应信息
            InputStream is = socket.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));

            String info = null;
            while ((info = br.readLine()) != null) {
                System.out.println(info);
            }

            //关闭资源
            br.close();
            is.close();
            oos.close();
            os.close();
            socket.close();

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

例:基于UDP的数据传递

服务端:

public class SocketServer {
    public static void main(String[] args) {

        try {

            byte[] bytes = new byte[1024];
            //创建一个包对象
            DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
            //创建一个socket对象
            DatagramSocket socket = new DatagramSocket(8888);
            //接收消息
            socket.receive(packet);
            //将字节数组转换为字符串
            String msg = new String(packet.getData(), 0,
                    packet.getLength());
            //输出客户端的IP地址和消息
            System.out.println(packet.getAddress().getHostAddress() + ":" + msg);

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

    }
}

客户端:

public class SocketClient {
    public static void main(String[] args) {

        try {
            //定义要发送的消息
            String msg = "用户名:张三 密码:123";
            //获取服务器的地址
            InetAddress add = InetAddress.getByName("localhost");
            //创建packet包对象,封装要发送的包数据和服务器地址和端口号
            DatagramPacket packet = new DatagramPacket(msg.getBytes(),
                    msg.getBytes().length, add, 8888);
            //创建Socket对象
            DatagramSocket socket = new DatagramSocket();
            //发送消息到服务器
            socket.send(packet);
            //关闭socket
            socket.close();

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

    }
}
(0)

相关推荐

  • Java Scoket实现双向通信代码详解

    你好我是辰兮,很高兴你能来阅读,本篇总结了Java Scoket类的相关知识,并且整理了实现双向通信的相关代码也有案例实现截图,分享获取新知,大家一起进步. 一.网络通信 网络通信,在网络中程序(发送者)与程序(接受者)之间的数据交互. 通信要素①ip + 端口号 ②传输协议 java.net包: 包含了Java用于网络通信所需的类. ServerSocket类,用于表示网络服务 创建网络服务(创建ServerSocket对象) //构造器 public ServerSocket(int por

  • Python基于stuck实现scoket文件传输

    使用socket中的struck来实现客户端发送 服务端: 客户端: # -*- coding: UTF-8 -*- import socket, time, socketserver, struct, os, _thread host = '127.0.0.1' port = 12307 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 定义socket类型 s.bind((host, port)) # 绑定需要监听的Ip和端口号,

  • Datagram Scoket双向通信

    这里是两个人进行通信.是根据ip来判断的,xp与xp之间没有问题,我win7和xp有问题(已解决 关闭防火墙,如果是内网 网段要一致) 复制代码 代码如下: import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.Ine

  • C# 实现Scoket心跳机制的方法

    TCP网络长连接 手机能够使用联网功能是因为手机底层实现了TCP/IP协议,可以使手机终端通过无线网络建立TCP连接.TCP协议可以对上层网络提供接口,使上层网络数据的传输建立在"无差别"的网络之上. 建立起一个TCP连接需要经过"三次握手": 第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认: 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+

  • 基于Java的Scoket编程

    目录 一,网络编程中两个主要的问题 二,两类传输协议:TCP和UDP TCP和UDP的区别 三,基于Socket的java网络编程 1.什么是Socket 2.Socket通讯的过程 3.创建Socket 代码演示 例:基于TCP的数据传输,传递字符串 例:基于TCP的数据传输,传输对象 例:基于多线程的通讯请求,多客户端访问服务器 例:基于UDP的数据传递 一,网络编程中两个主要的问题 一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输. 在TCP/IP协

  • 基于Java实现Socket编程入门

    目录 认识Socket 建立socket的基本流程 1.最基本的Socket示范 1.1单向通信 1.2双向通信 2.发送更多的消息:结束的界定 2.1使用特殊符号 2.2根据长度界定 3.处理更多的连接:多线程 3.1同时实现消息的发送与接收 3.2使用线程池优化服务端并发能力 4.连接保活 4.1使用心跳包 4.2断开时重连 认识Socket socket,又称套接字,是在不同的进程间进行网络通讯的一种协议.约定或者说是规范. 对于socket编程,它更多的时候像是基于TCP/UDP等协议做

  • Java文件(io)编程_基于File类的基本用法(必看篇)

    1.首先了解文件流的相关概念: 2.文件File类的基本用法 public class Demo_1 { public static void main(String[] args) { //创建一个文件对象 File f=new File("e:\\aa.txt"); //得到文件的路径 System.out.println("文件路径:"+f.getAbsolutePath()); //得到文件的大小,字节数 System.out.println("文

  • 基于Java网络编程和多线程的多对多聊天系统

    1.前言 程序实现基于星型结构(服务器接收来自各个客户端发送的信息,然后将信息传递给其他客户端界面并在其他客户端界面显示发送的信息) 2.类图 3.代码 客户端代码: package netProgram; import java.io.IOException; import java.net.Socket; import java.net.SocketAddress; public class Client implements ScreenInputInterface{ private So

  • Java基于IDEA实现http编程的示例代码

    http开发前言之为什么要有应用层 我们已经学过TCP/IP , 已经知道目前数据能从客户端进程经过路径选择跨网络传送到服务器端进程 [ IP+Port ],可是,仅仅把数据从A点传送到B点就完了吗?这就好比,在淘宝上买了一部手机,卖家[ 客户端 ]把手机通过顺丰[ 传送+路径选择 ] 送到买家 [ 服务器 ] 手里就完了吗?当然不是,买家还要使用这款产品,还要在使用之后,给卖家打分评论.所以,我们把数据从A端传送到B端, TCP/IP 解决的是顺丰的功能,而两端还要对数据进行加工处理或者使用,

  • java基于AspectJ(面向切面编程)编码示例分享

    一.基本概念 AspectJ是一种面向切面程序设计的基于Java 的实现.它向 Java 中加入了连接点(Join Point)这个新概念,其实它也只是现存的一个 Java概念的名称而已.它向 Java 语言中加入少许新结构:切点(pointcut).通知(Advice).类型间声明(Inter-type declaration)和方面(Aspect).切点和通知动态地影响程序流程,类型间声明则是静态的影响程序的类等级结构,而切面则是对所有这些新结构的封装. 基于切面.连接点.切点.通知的概念如

  • 基于java编写局域网多人聊天室

    由于需要制作网络计算机网络课程设计,并且不想搞网络布线或者局域网路由器配置等等这种完全搞不懂的东西,最后决定使用socket基于java编写一个局域网聊天室: 关于socket以及网络编程的相关知识详见我另一篇文章:Java基于socket编程 程序基于C/S结构,即客户端服务器模式. 服务器: 默认ip为本机ip 需要双方确定一个端口号 可设置最大连接人数 可启动与关闭 界面显示在线用户人以及姓名(本机不在此显示) 客户端: 需要手动设置服务器ip地址(局域网) 手动设置端口号 输入姓名 可连

  • Java 多线程并发编程_动力节点Java学院整理

    一.多线程 1.操作系统有两个容易混淆的概念,进程和线程. 进程:一个计算机程序的运行实例,包含了需要执行的指令:有自己的独立地址空间,包含程序内容和数据:不同进程的地址空间是互相隔离的:进程拥有各种资源和状态信息,包括打开的文件.子进程和信号处理. 线程:表示程序的执行流程,是CPU调度执行的基本单位:线程有自己的程序计数器.寄存器.堆栈和帧.同一进程中的线程共用相同的地址空间,同时共享进进程锁拥有的内存和其他资源. 2.Java标准库提供了进程和线程相关的API,进程主要包括表示进程的jav

  • 基于Java中的数值和集合详解

    数组array和集合的区别: (1) 数值是大小固定的,同一数组只能存放一样的数据. (2) java集合可以存放不固定的一组数据 (3) 若程序事不知道究竟需要多少对象,需要在空间不足时自动扩增容量,则需要使用容器类库,array不适用 数组转换为集合: Arrays.asList(数组) 示例: int[] arr = {1,3,4,6,6}; Arrays.asList(arr); for(int i=0;i<arr.length;i++){ System.out.println(arr[

  • 基于java中byte数组与int类型的转换(两种方法)

    java中byte数组与int类型的转换,在网络编程中这个算法是最基本的算法,我们都知道,在socket传输中,发送.者接收的数据都是 byte数组,但是int类型是4个byte组成的,如何把一个整形int转换成byte数组,同时如何把一个长度为4的byte数组转换为int类型.下面有两种方式. public static byte[] int2byte(int res) { byte[] targets = new byte[4]; targets[0] = (byte) (res & 0xf

随机推荐