使用Socket进行通信

客户端通常可使用Socket的构造器来连接到指定服务器,Socket通常可使用如下两个构造器。

Socket(lnetAddress/String  remoteAddress , int  port):创建连接到指定远程主机、远程端口的Socket,该构造器没有指定本地地址、本地端口,默认使用本地主机的默认IP地址,默认使用系统动态指定的IP地址。

Socket(lnetAddress/String  remoteAddress , int  port , lnetAddress  localAddr , int  localPort):创建连接到指定远程主机、远程端口的Socket,并指定本地IP地址和本地端口号,适用于本地主机有多个IP地址的情形。

上面两个构造器中指定远程主机时既可使用lnetAddress来指定,也可直接使用String对象来指定,但程序通常使用String对象(如192.168.2.23)来指定远程IP。当本地主机只有一个IP地址时,使用第一个方法更为简单。如以下代码所示:

//创建连接到本机、30000端口的Socket
Socket s = new Socket("172.18.5.198", 30000);
//下面就可以使用Socket进行通信了

......

当程序执行上面代码时,该代码将会连接到指定服务器,让服务器的ServerSocket的accept()方法向下执行,于是服务器端和客户端就产生一对互相连接的Socket。

当客户端、服务器端产生了对应的Socket之后,程序无须再去分服务端、客户端,而是通过各自的Socket进行通信。Socket提供了如下两个方法来获取输入流和输出流:

InputStream  getInputStream():返回该Socket对象对应的输入流,让程序通过该输入流从Socket中取出数据。

OnputStream  getOnputStream():返回该Socket对象对应的输出流,让程序通过该输出流向Socket中输出数据。

通过这两个方法返回的InputStream和OutputStream,可以得出:不管底层的IO流是怎样的节点流、文件流也好,网络Socket产生的流也好,程序都可以将其包装成处理流,从而提供更多方便的处理。

下面以一个最简单的网络通信程序为例来介绍基于TCP协议的网络通信:

下面的服务器程序需要在PC上运行,它仅仅建立ServerSocket监听,并使用Socket获取输出流输出。

import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class SimpleServer {
public static void main(String[] args) throws IOException {
  //创建一个ServerSocket,用于监听客户端Socket的连接请求
  ServerSocket ss = new ServerSocket(30000);
  //采用循环不断接受来自客户端的请求
  while(true){
    //每当接收到客户端Socket的请求,服务器端也对应产生一个Socket
    Socket s = ss.accept();
    OutputStream os = s.getOutputStream();
    os.write("你好!你收到了服务器的新年祝福:\n".getBytes("utf-8"));
    //关闭输出流,关闭Socket
    os.close();
    s.close();
    }
  }

}

上面的程序中建立了一个ServerSocket对象,该ServerSocket在30000端口监听,该ServerSocket将会一直监听,等待客户端程序的连接,程序接下来的代码用于打开Socket对应输出流,并向输出流中写入一段字符串数据。

上面的程序并未把OutputStream流包装成PrintStream,然后使用PrintStream直接输出整个字符串,这是因为该服务器端程序运行于Windows主机上,当直接使用PrintStream输出字符串时默认使用系统平台的字符串(即GBK)进行编码;但该程序的客户端是Android应用,运行于Linux平台(Android是Linux内核的),因此当客户端读取网络数据时默认使用UTF-8字符集进行解码,这样势必引起乱码,为了保证客户端能正常解析到数据,此处手动控制字符串的编码、强行指定使用UTF-8字符集进行编码,这样就可避免乱码问题了。

接下来的客户端也仅仅使用Socket建立与指定IP、指定端口的连接,并使用Socket获取输入流读取数据,该客户端程序是一个Android应用,因此还是需要先建立Android项目,该程序的界面中包含一个文本框,用于显示从服务器端读取的字符串数据。

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.Socket;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.EditText;

public class SimpleClient extends Activity {
  EditText show;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_simple_client);
    show = (EditText) findViewById(R.id.show);
    //关闭输入流、socket
    try {
      Socket socket = new Socket("172.18.5.88", 30000);
      //将Socket对应的输入流包装成BufferReader
      BufferedReader br = new BufferedReader(
            new InputStreamReader(socket.getInputStream()));
      //进行普通IO操作
      String line = br.readLine();
      show.setText("来自服务器的数据"+line);
      br.close();
      socket.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

}

上面的程序中使用ServerSocket和Socket建立网络连接后,接下来通过Socket获取输入流、输出流进行通信。不难看出,一旦使用ServerSocket、Socket建立网络连接,程序通过网络通信与普通IO并没有太大的区别。

该Android应用需要访问互联网,因此还需要为该应用赋予访问互联网的权限,也就是在AndroidManifest.xml文件中增加如下配置片段:

<!-- 授权访问互联网 -->
<uses-permission android:name="android.permission.INTERNET"/>

先运行上面程序中的SimpleServer类,将看到服务器一直处于等待状态,因为服务器使用了死循环来接收来自客户端的请求;再运行客户端AndroidClient类,将看到程序输出:“来自服务器的数据:你好,你收到了服务器的新年祝福!”这表明客户端和服务端通信成功。

实际应用中,程序可能不想让执行网络连接、读取服务器数据的进程一直阻塞,而是希望当网络连接、读取操作超过合理时间之后,系统自动认为该操作失败,这个合理时间就是超时时间。Socket对象提供了一个setSoTimeout(int  timeout)来设置超时时长,如下面的代码:

Socket  s = new  Socket("127.0.0.1" ,  30000);

//设置10秒之后即认为超时

s.setSoTimeout(10000);

为Socket对象指定了超时时长之后,如果使用Socket进行读、写操作完成之前已经超出了该时间限制,那么这些方法就会抛出SocketTimeoutException异常,程序可以对该异常进行捕捉,并进行适当处理。如以下代码:

try {
  //使用Scanner来读取网络输入流中的数据
  Scanner scan = new Scanner(s.getInputStream());
  //读取一行字符
  String line = scan.nextLine();
}
//捕捉SocketTimeoutException异常
catch (SocketTimeoutException e) {
  // 对异常进行处理

  ......
}

假设程序需要为Socket连接服务器时指定超时时长:即经过指定时间后,如果该Socket还未连接到远程服务器,则系统认为该Socket连接超时。但Socket的所有构造器里都没有提供指定超时时长的参数,所以程序应该先创建一个无连接的Socket,再调用Socket的connect()方法来连接远程服务器,而connect方法就可以接受一个超时时长参数,如以下代码:

//创建一个无连接的Socket
Socket s = new Socket();
//让该Socket连接到远程服务器,如果经过10秒还没有连接到,则认为连接超时
s.connect(new InetAddress(host,port), 1000);

时间: 2024-08-08 02:40:22

使用Socket进行通信的相关文章

java socket线程通信

关于socket线程通信的一些知识整理 一般我们需要要让两台机子进行通信,需要创建一个Server 类,一个Client类,还需要创建一个线程类 server public class Server { public static void main(String[] args) throws IOException {  ServerSocket ss = new ServerSocket(8888);  int num=0;  System.out.println("服务器即将启动,   等

java socket报文通信(一)socket的建立

java socket报文通信(一) socket的建立  今天来和大家分享一下java中如何使用socket进行通信.先来啰嗦两句,看看Tcp/ip和udp: TCP是Transfer Control Protocol的 简称,是一种面向连接的保证可靠传输的协议.通过TCP协议传输,得到的是一个顺序的无差错的数据流.发送方和接收方的成对的两个socket之间必须建 立连接,以便在TCP协议的基础上进行通信,当一个socket(通常都是server socket)等待建立连接时,另一个socke

Android---50---使用Socket进行通信

使用Socket进行通信: 通过Socket的构造方法连接指定的服务器: 两个构造方法: Socket(InetAddress/String remoteAddress,int port): 创建连接到指定远程主机.远程端口的Socket,该构造器没有指定本地地址,本地端口,默认使用本地主机的默认IP 地址,默认使用系统动态指定的IP地址 Socket(InetAddress/String remoteAddress,int port,InetAddress localAddr,int loca

服务端Socket多线程通信

写在前面的话:整了一个月的团支部评比,中间还要弄智能车锁的项目,真是忙的天昏地暗飞沙走石,时隔一个月来更新一下博客. 智能车锁:做成与ofo一样的共享项目,目前是前期开发阶段,用到一个socket多线程通信的技术,做一下笔记. 一.socket多线程通信概念 现在的网络进程都是通过socket来通信的,socket连接是一种可持续的长连接,不详http协议是请求-响应形式的短连接.多线程通信是为了解决多个客户端设备与一个服务端设备的通信问题,要求每个客户端与服务端的连接不能相互影响,所以需使用多

Socket进程通信机制

1.Socket通常称为"套接字",用于描述IP地址和端口,是一个通信链的句柄. 2.应用程序通过套接字向网络发出请求或者应答网络请求. 3.Socket既不是一个程序,也不是一种协议,其只是操作系统提供的通信层的一组抽象API. 4.进程通信的相关概念: 网间进程通信要解决的是不同主机进程间相互通信问题.为此,首先要解决的是网间进程标识问题.同一主机上,不同进程可用唯一进程号(Process ID)标识. (1)端口:网络中可以被命名和寻址的通信端口,是操作系统可分配的一种资源,用于

Java Socket编程----通信是这样炼成的

Java最初是作为网络编程语言出现的,其对网络提供了高度的支持,使得客户端和服务器的沟通变成了现实,而在网络编程中,使用最多的就是Socket.像大家熟悉的QQ.MSN都使用了Socket相关的技术.下面就让我们一起揭开Socket的神秘面纱. Socket编程 一.网络基础知识(参考计算机网络)            关于计算机网络部分可以参考相关博客:           <TCP/IP协议栈及OSI参考模型详解> http://wangdy.blog.51cto.com/3845563/

java socket报文通信(二)报文的封装

昨天我们谈了怎么建立socket通信的服务端和客户端,今天我们就来谈一谈怎么封装报文. 什么是报文这里我就不在阐述了,不清楚的朋友可以自己去查资料.我们今天要谈的报文主要友以下几个部分组成: 3位同步校验位+8位报文长度+报文头+报文体+32位MD5校验位 基本格式如下: 0X110X120X1300000232<?xml version="1.0" encoding="GBK"?><ROOT><Code>0204</Cod

慕课网_Java Socket应用---通信是这样练成的

fad 第1章 网络基础知识 1-1 网络基础简介 (10:21) 第2章 Java 中网络相关 API 的应用 2-1 Java 中的 InetAddress 的应用 (08:10) import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Arrays; public class Hello { public static void main(String[] args) throw

Socket的通信机制?

套接字(socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元.它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口. 应用层通过传输层进行数据通信时,TCP会遇到同时为多个应用程序进程提供并发服务的问题.多个TCP连接或多个应用程序进程可能需要通过同一个 TCP协议端口传输数据.为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了