ホームページ >Java >&#&チュートリアル >Java でのソケット プログラミングの例を共有する (写真)

Java でのソケット プログラミングの例を共有する (写真)

黄舟
黄舟オリジナル
2017-05-28 09:20:362201ブラウズ

ソケットは私たちにとって非常に実用的です。以下はこの研究のためのメモです。これは主に、例外タイプ、対話原則、ソケット、サーバーソケット、およびマルチスレッドに分かれています。リアルタイム アプリケーションやリアルタイム ゲームの場合、HTTP プロトコルではニーズを満たせないことがよくあります。現時点では、Socket は私たちにとって非常に実用的です。以下はこの研究のためのメモです。主に、例外の種類、相互作用の原則、Socket、ServerSocket、およびマルチスレッドの観点から説明されます。


例外タイプ Socket の内容を理解する前に、まず、関連する例外タイプのいくつかを理解する必要があります。次の 4 つの型はすべて IOException を継承しているため、その多くは IOException を直接ポップアップする可能性があります。

UnkownHostException: ホスト名またはIPエラー

ConnectException: サーバーが接続を拒否しました、サーバーが起動しませんでした、(キュー数を超えました、接続が拒否されました)

SocketTimeoutException: 接続がタイムアウトしました
BindException: Socketオブジェクト指定されたローカル IP アドレスまたはポートにバインドすることはできません


対話プロセス Socket と ServerSocket の間の対話については、以下の図で詳細かつ明確に説明されていると思います。


ソケットコンストラクター

Socket()Socket(InetAddress address, int port)throws UnknownHostException, IOException

Socket(InetAddress address, int port, InetAddress localAddress, int localPort)th rowsIOException

ソケット ( String host, int port)throws UnknownHostException, IOException
Socket(String host, int port, InetAddress localAddress, int localPort)throws IOException


パラメーターのない最初のコンストラクターを除き、他のコンストラクターはサーバーとの接続を確立しようとします。 。失敗した場合は、IOException エラーがスローされます。成功すると、Socket オブジェクトが返されます。

InetAddress は、ホストを記録するために使用されるクラスです。その静的 getHostByName(String msg) はインスタンスを返すことができ、その静的メソッド getLocalHost() は現在のホストの IP アドレスを取得してインスタンスを返すこともできます。 Socket(String host, int port, InetAddress localAddress, int localPort) コンストラクターのパラメーターは、それぞれターゲット IP、ターゲット ポート、バインドされたローカル IP、およびバインドされたローカル ポートです。


ソケットメソッド

getInetAddress(); リモートサーバーのIPアドレスgetPort(); リモートサーバーのポート

getLocalAddress() ローカルクライアントのIPアドレス

getLocalPort()ローカルクライアントの
getInputStream() ; 入力ストリームを取得する
getOutStream(); 出力ストリームを取得する

これらのメソッドの中で、最も重要なものは getInputStream() と getOutputStream() であることに注意してください。


ソケットステータス

isClosed(); //接続が閉じられているかどうか、閉じられている場合はtrueを返し、それ以外の場合はfalseを返しますisConnect(); //以前に接続されていた場合はtrueを返します。それ以外の場合は return false

isBound(); //Socket がローカルポートにバインドされている場合は true を返し、それ以外の場合は false を返します


Socket が接続されているかどうかを確認したい場合は、次のステートメントが良い方法です。 。

boolean isConnection=socket.isConnected() && !socket.isClosed(); //接続が現在進行中かどうかを判断します


ソケットを半分閉じます

多くの場合、わかりません取得する入力ストリームの内容 読み取りを完了するまでにどのくらい時間がかかりますか?以下に一般的なメソッドをいくつか示します。


 カスタム識別子 (以下の例のように、「bye」文字列を受信したらソケットを閉じます)
  •  読み取り長を通知します (一部のカスタム プロトコル、最初の読み取り長を示すためにいくつかのバイトが固定されています)
  •  すべてのデータを読み取ります
  •  close呼び出し時にSocketが閉じられたら、その入出力ストリームを閉じます

ServerSocketコンストラクター

注:

1. バックログクライアント接続リクエストのキューの長さ。ポートが占有されている場合、または特定のポートを使用する権限がない場合は、BindException エラーがスローされます。たとえば、ポート 1 ~ 1023 には、管理者にバインドする権限が必要です。 3. ポートが 0 に設定されている場合、システムは自動的にポートを割り当てます。

4. bindAddr用于绑定服务器IP,为什么会有这样的设置呢,譬如有些机器有多个网卡。

5. ServerSocket一旦绑定了监听端口,就无法更改。ServerSocket()可以实现在绑定端口前设置其他的参数。 

单线程的ServerSocket例子 


public void service(){
  while(true){
    Socket socket=null;
    try{
      socket=serverSocket.accept();//从连接队列中取出一个连接,如果没有则等待
      System.out.println("新增连接:"+socket.getInetAddress()+":"+socket.getPort());
      ...//接收和发送数据
    }catch(IOException e){e.printStackTrace();}finally{
      try{
        if(socket!=null) socket.close();//与一个客户端通信结束后,要关闭Socket
      }catch(IOException e){e.printStackTrace();}
    }
  }
}

多线程的ServerSocket

多线程的好处不用多说,而且大多数的场景都是多线程的,无论是我们的即时类游戏还是IM,多线程的需求都是必须的。下面说说实现方式:

  •  主线程会循环执行ServerSocket.accept();

  •  当拿到客户端连接请求的时候,就会将Socket对象传递给多线程,让多线程去执行具体的操作;

实现多线程的方法要么继承Thread类,要么实现Runnable接口。当然也可以使用线程池,但实现的本质都是差不多的。

这里举例:

下面代码为服务器的主线程。为每个客户分配一个工作线程:


public void service(){
  while(true){
    Socket socket=null;
    try{
      socket=serverSocket.accept();            //主线程获取客户端连接
      Thread workThread=new Thread(new Handler(socket));  //创建线程
      workThread.start();                  //启动线程
    }catch(Exception e){
      e.printStackTrace();
    }
  }
}

当然这里的重点在于如何实现Handler这个类。Handler需要实现Runnable接口: 


class Handler implements Runnable{
  private Socket socket;
  public Handler(Socket socket){
    this.socket=socket;
  }
  
  public void run(){
    try{
      System.out.println("新连接:"+socket.getInetAddress()+":"+socket.getPort());
      Thread.sleep(10000);
    }catch(Exception e){e.printStackTrace();}finally{
      try{
        System.out.println("关闭连接:"+socket.getInetAddress()+":"+socket.getPort());
        if(socket!=null)socket.close();
      }catch(IOException e){
        e.printStackTrace();
      }
    }
  }
}

当然是先多线程还有其它的方式,譬如线程池,或者JVM自带的线程池都可以。这里就不说明了。

以上がJava でのソケット プログラミングの例を共有する (写真)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。