Java的Socket通讯基础编程完全指南

什么是Socket
网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个Socket。Socket通常用来实现客户方和服务方的连接。Socket是TCP/IP协议的一个十分流行的编程界面,一个Socket由一个IP地址和一个端口号唯一确定。
但是,Socket所支持的协议种类也不光TCP/IP一种,因此两者之间是没有必然联系的。在Java环境下,Socket编程主要是指基于TCP/IP协议的网络编程。

Socket通讯的过程
Server端Listen(监听)某个端口是否有连接请求,Client端向Server 端发出Connect(连接)请求,Server端向Client端发回Accept(接受)消息。一个连接就建立起来了。Server端和Client 端都可以通过Send,Write等方法与对方通信。
对于一个功能齐全的Socket,都要包含以下基本结构,其工作过程包含以下四个基本的步骤:
  (1) 创建Socket;
  (2) 打开连接到Socket的输入/出流;
  (3) 按照一定的协议对Socket进行读/写操作;
  (4) 关闭Socket.(在实际应用中,并未使用到显示的close,虽然很多文章都推荐如此,不过在我的程序中,可能因为程序本身比较简单,要求不高,所以并未造成什么影响。)

创建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则表示服务端所能支持的最大连接数。例如:学习视频网 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,在程序中必须对之作出处理。所以在创建Socket或ServerSocket是必须捕获或抛出例外。

代码

server

 package socket; 

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

  public class TcpServer {
    public static void main(String[] args) throws Exception {
      ServerSocket server = new ServerSocket(9091);
      try {
        Socket client = server.accept();
        try {
          BufferedReader input =
              new BufferedReader(new InputStreamReader(client.getInputStream()));
          boolean flag = true;
          int count = 1; 

          while (flag) {
            System.out.println("客户端要开始发骚了,这是第" + count + "次!");
            count++; 

            String line = input.readLine();
            System.out.println("客户端说:" + line); 

            if (line.equals("exit")) {
              flag = false;
              System.out.println("客户端不想玩了!");
            } else {
              System.out.println("客户端说: " + line);
            } 

          }
        } finally {
          client.close();
        } 

      } finally {
        server.close();
      }
    }
  }

client

  package socket; 

  import java.io.*;
  import java.net.*;
  import java.util.Scanner; 

  public class TcpClient {
    public static void main(String[] args) throws Exception {
      Socket client = new Socket("127.0.0.1", 9091);
      try {
        PrintWriter output =
            new PrintWriter(client.getOutputStream(), true);
        Scanner cin = new Scanner(System.in);
        String words; 

        while (cin.hasNext()) {
          words = cin.nextLine(); 

          output.println(words); 

          System.out.println("写出了数据: " + words);
        } 

        cin.close();
      } finally {
        client.close();
      }
    }
  }

Server绑定ip

用c写socket的时候,struct sockaddr_in 结构体是可以指定sin_addr.s_addr的,也就是可以指定ip地址,为什么会有这种需求呢,例如我的网络链接是这样的:

我可能只想绑定eth0这个网卡的ip地址,因为我的lo和wlan0都可能在用一端口做了nginx的虚拟主机,因此在服务器端开启ServerSocket的时候,有指定ip的需求

方案
ServerSocket的一个构造函数如下:

public ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException

参数:

port - 本地 TCP 端口
    backlog - 侦听 backlog
    bindAddr - 要将服务器绑定到的 InetAddress

因为InetAddress无构造函数,我在这里纠结了好一段时间,查看stackoverflow上,可以使用InetAddress的getByName方法

示例代码

  InetAddress bindip = InetAddress.getByName("192.168.1.168"); 

  ServerSocket server = new ServerSocket(9091, 0, bindip);

并发访问
服务器端通过增加多线程来同时处理多个客户端的请求,其实实现还是很水的,毕竟java对多线程封装也足够好了,我是在Server服务器端用一个内部类实现了Runnable接口,在run方法里处理客户端的请求,将数据打印出来

server代码

package capitalsocket; 

  import java.io.BufferedReader;
  import java.io.IOException;
  import java.io.InputStreamReader;
  import java.net.InetAddress;
  import java.net.ServerSocket;
  import java.net.Socket; 

  public class CapitalizeServer {
    private static int clientNum = 0; 

    public static void main(String args[]) throws Exception {
      ServerSocket listener = new ServerSocket(9898, 0, InetAddress.getByName("192.168.1.168"));
      try {
        while (true) {
          Capitalizer multip = new Capitalizer(listener.accept(), CapitalizeServer.clientNum ++);
          Thread t = new Thread(multip);
          t.start();
        }
      } finally {
        listener.close();
      }
    } 

    private static class Capitalizer implements Runnable {
      private Socket client;
      private int id; 

      public Capitalizer(Socket s, int id) {
        this.client = s;
        this.id = id;
      } 

      public void run() {
        try {
          BufferedReader input =
              new BufferedReader(new InputStreamReader(this.client.getInputStream())); 

          while (true) {
            String data = input.readLine(); 

            if (data.equals("bye")) {
              System.out.println("当前第" + this.id + "个客户端度不想玩了!");
              break;
            } else {
              System.out.println("当前第" + this.id + "个客户端说:" + data);
            }
          } 

        } catch (IOException e) {
          e.printStackTrace();
        } finally {
          try {
            this.client.close();
          } catch (IOException e) {
            e.printStackTrace();
          }
        }
      }
    } 

  }

client代码
客户端代码基本没变,增加了一个退出操作

package capitalsocket; 

  import java.io.PrintWriter;
  import java.net.Socket;
  import java.util.Scanner; 

  public class CapitalizeClient {
    public static void main(String[] args) throws Exception {
      Socket client = new Socket("192.168.1.168", 9898);
      try {
        PrintWriter output = new PrintWriter(client.getOutputStream(), true);
        Scanner cin = new Scanner(System.in);
        String words; 

        while (cin.hasNext()) {
          words = cin.nextLine();
          output.println(words); 

          if (words.equals("bye")) {
            break;
          } 

          // 每写一次数据需要sleep一会
          Thread.sleep(3000);
        } 

        cin.close();
      } finally {
        client.close();
      }
    }
  }
(0)

相关推荐

  • Java Socket编程详解及示例代码

    Socket,又称为套接字,Socket是计算机网络通信的基本的技术之一.如今大多数基于网络的软件,如浏览器,即时通讯工具甚至是P2P下载都是基于Socket实现的.本文会介绍一下基于TCP/IP的Socket编程,并且如何写一个客户端/服务器程序. 餐前甜点 Unix的输入输出(IO)系统遵循Open-Read-Write-Close这样的操作范本.当一个用户进程进行IO操作之前,它需要调用Open来指定并获取待操作文件或设备读取或写入的权限.一旦IO操作对象被打开,那么这个用户进程可以对这个

  • Java网络通信基础编程(必看篇)

    方式一:同步阻塞方式(BIO): 服务器端(Server): package com.ietree.basicskill.socket.mode1; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; /** * 服务端 */ public class Server { // 端口号 final static int PORT = 8765; public static void ma

  • Java网络编程基础教程之Socket入门实例

    当我们想要在Java中使用TCP/IP通过网络连接到服务器时,就需要创建java.net.Socket对象并连接到服务器.假如希望使用Java NIO,也可以创建Java NIO中的SocketChannel对象. 创建Socket 下面的示例代码是连接到IP地址为78.64.84.171服务器上的80端口,这台服务器就是我们的Web服务器(www.jb51.net),而80端口就是Web服务端口. 复制代码 代码如下: Socket socket = new Socket("78.46.84.

  • Java的Socket通讯基础编程完全指南

    什么是Socket 网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个Socket.Socket通常用来实现客户方和服务方的连接.Socket是TCP/IP协议的一个十分流行的编程界面,一个Socket由一个IP地址和一个端口号唯一确定. 但是,Socket所支持的协议种类也不光TCP/IP一种,因此两者之间是没有必然联系的.在Java环境下,Socket编程主要是指基于TCP/IP协议的网络编程. Socket通讯的过程 Server端Listen(监听)某个端口

  • Java基于Socket实现网络编程实例详解

    一,网络编程中两个主要的问题 一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输. 在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的路由,由IP地址可以唯一地确定Internet上的一台主机. 而TCP层则提供面向应用的可靠(tcp)的或非可靠(UDP)的数据传输机制,这是网络编程的主要对象,一般不需要关心IP层是如何处理数据的. 目前较为流行的网络编程模型是客户机/服务器(C/S)结构.即通信双方一方作为服务器等待客户提出请求并予以响应.客户则

  • Java中Socket用法详解

    目录 1 问题引入 1.1 网络架构模型 1.1.1 OSI参考模型 1.1.2 TCP/IP五层模型 1.1.3 各协议层的说明 1.2 网络编程中的问题 1.3 TCP协议与UDP协议 1.3.1 TCP 1.3.2 UDP 1.3.3 TCP和UDP的区别 2 socket网络编程 2.1什么是socket? 2.2 Socket的原理 3 基于java的socket网络编程实现 3.2 基于UDP的socket实现 1 问题引入 1.1 网络架构模型 网络架构模型主要有OSI参考模型和T

  • 基于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 Socket聊天室编程(二)之利用socket实现单聊聊天室

    在上篇文章Java Socket聊天室编程(一)之利用socket实现聊天之消息推送中我们讲到如何使用socket让服务器和客户端之间传递消息,达到推送消息的目的,接下来我将写出如何让服务器建立客户端与客户端之间的通讯. 其实就是建立一个一对一的聊天通讯. 与上一篇实现消息推送的代码有些不同,在它上面加以修改的. 如果没有提到的方法或者类则和上一篇一模一样. 1,修改实体类(服务器端和客户端的实体类是一样的) 1,UserInfoBean 用户信息表 public class UserInfoB

  • Java Socket聊天室编程(一)之利用socket实现聊天之消息推送

    相关阅读:Java Socket聊天室编程(二)之利用socket实现单聊聊天室 网上已经有很多利用socket实现聊天的例子了,但是我看过很多,多多少有一些问题存在. 这里我将实现一个比较完整的聊天例子,并解释其中的逻辑. 由于socket这一块比较大,所以我将分出几篇来写一个比较完整的socket例子. 这里我们先来实现一个最简单的,服务器与客户端通讯,实现消息推送的功能. 目的:服务器与客户端建立连接,客户端可以向服务器发送消息,服务器可以向客户端推送消息. 1,使用java建立socke

  • Java socket通讯实现过程及问题解决

    这篇文章主要介绍了Java socket通讯实现过程及问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 本来是打算验证java socket是不是单线程操作,也就是一次只能处理一个请求,处理完之后才能继续处理下一个请求.但是在其中又发现了许多问题,在编程的时候需要十分注意,今天就拿出来跟大家分享一下. 首先先建立一个服务端代码,运行时也要先启动此程序. package com.test.some.Socket; import java.i

  • Java使用Socket简单通讯详解

    目录 Java实现基于Socket的简单通信  一.ServerSocket 1.使用JavaFX写的小界面,方便观察客户端连接情况 2.创建ServerSocket并处理客户端连接并显示客户端基本信息 3.新建Handle类处理接收发送两个客户端的消息 二.Socket 1.同样的编写一个客户端界面 2.创建Socket连接客户端并获取输入输出流 3.添加编辑框监听处理消息发送 4.创建新线程从服务器上接收消息 三.测试 四.总结 1.原理流程 2.不足之处 Java实现基于Socket的简单

  • Android 模拟器(JAVA)与C++ socket 通讯 分享

    C++ 作为Client端view plaincopy to clipboardprint? 复制代码 代码如下: // Client.cpp : Defines the entry point for the console application.     //     #include "stdafx.h"     #include      #pragma comment(lib,"ws2_32.lib")     #define  MAX_BUF_SIZE

  • 学习 NodeJS 第八天:Socket 通讯实例

    前言 一般来讲,HTTP 是基于文本的"单向"通讯机制.这里所谓的"单向",乃相对于"双向"而言,因为 HTTP 服务器只需根据请求返还恰当的 HTML 给客户端即可,不涉及客户端向服务端的通讯.这种单向的机制比较简单,对网络质量要求也不高.而更多的场景则是需要可靠.稳定的端到端连接.一般这种服务是实时的.有态的而且是长连接,长连接则暗示两段须达致相向通讯的能力,也就说是服务端客户端两者间能够实时地相互间通信.毫无疑问,能够实时通信的服务器正是我

随机推荐