Java网络编程基础之Scoket通信

      在java中提供了一系列的访问网络资源的工具类,在学习理解Scoket(套接字编程)时首先需要了解俩个东西:

      1:TCP/IP和IP

             为了进行网络通信,通信双方必须遵守通信协议.目前最广泛使用的是TCP/IP协议,它是Internet中各方所遵循的公共协                   议.TCP(Transport Control Protocol)是一种传输控制协议,IP(Internet Protocol)是一种网际协议(代表计算机的地址),               TCP/IP代表这两个协议的。

   2:InetAddress类

         Java.net包中有InetAddress类的定义,InetAddress类的对象用于IP地址和域名,该类提供以下方法:

         getByName(String s):获得一个InetAddress 类的对象,该对象中含有主机的IP地址和域名,该对象用如下格式表示它包含 的信息: www.baidu.com/202.108.37.40;

         String getHostName():获取InetAddress对象的域名;

         String getHostAddress():获取InetAddress对象的IP地址;

         getLocalHost():获得一个InetAddress对象,该对象含有本地机的域名和IP地址。

如:

         InetAddress addr = InetAddress.getByname(“www.baidu.com”);
          String domainName = addr.getHostName();//获得主机名
          String IPName = addr.getHostAddress();//获得IP地址
          System.out.println(domainName);
          System.out.println(IPName);

           输出结果为:www.baidu.com  \n  180.97.33.107

  3:socket基础 

      3.1 网络应用模式主要有:

          3.1.1:主机/终端模式:集中计算,集中管理;

          3.1.2:客户机/服务器(Client/Server,简称C/S)模式:分布计算,分布管理;

          3.1.3:浏览器/服务器模式:利用Internet跨平台。

       在客户机/服务器工作模式中,在Server端,要准备接受多个Client端计算机的通信。为此,除用IP地址标识Internet上的计算机       之外,另还引入端口号,用端口号标识正在Server端后台服务的线程。端口号与IP地址的组合称为网络套接字(socket)。

        3.2 Java语言在实现C/S模式中,套接字分为两类:

            在Server端,ServerSocket类支持底层的网络通信;

           在Client端,Socket类支持网络的底层通信。
           Server机通过端口(总线I/O地址)提供面向Client机的服务;Server机在它的几个不同端口分别同时提供几种不同的服务。            Client接入Server的某一端口,通过这个端口提请Server机为其服务。

         规定:端口号0~1023供系统专用。例如,HTTP协议在端口80,telnet协议在端口23。端口1024~65535供应用程序使用。

       3.3 具体使用

           3.3.1:新建客户端,使用Socket请求连接指定IP和port端口的服务器

             

            3.3.2:新建服务端,响应客户端的连接请求

             

             说明:ip是是本机的地址,port端口号是认为约定的,server.accept()是一个阻塞式方法,当有客户端连接进来才会往下执             行。也就是当有客户端连接到服务端的时候,socket就不为空了。

      以上代码能够把客户端和服务端之间建立连接,但是在实际项目中需要客户端和服务端进行通信,具体需求为客户端读取控制台     输入的字符串发送到服务端,service接受客户端的消息,打印在控制台,并且恢复client客户端消息,客户端接收恢复消息也打       印在控制台。

    具体实现如下:

          Client(客户端)

            public static void main(String[] args) {
// TODO Auto-generated method stub

Socket socket = null;//Socket套接字
PrintWriter os = null;   //输出类
BufferedReader br=null;//字符拂去缓冲流
try {  
// 实例化一个Socket套接字,向IP为127.0.0.1 端口为9086的机子发起会话
socket = new Socket(host, port);
// 实例化一个消息读取线程
new ClientreadMsg(socket).start();
os=new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())));
// 由Socket对象得到输入流,并构造相应的BufferedReader对象
// 由系统标准输入设备构造BufferedReader对象 字符读取
//InputStreamReader  把字节流转成字符流
br = new BufferedReader(new InputStreamReader(System.in));
String readline;
while (true) {
readline=br.readLine();
if (!readline.equalsIgnoreCase("bye")) {
// 若从标准输入读入的字符串为 "yes"则停止循环
// 将从系统标准输入读入的字符串输出到Server
os.println(readline);
// 刷新输出流,使Server马上收到该字符串
os.flush();
System.out.println("(提示:客户端发送到服务器的消息发送成功!

正在等待服务器返回消息,请稍候....)");
}else{
break;
}
}
} catch (Exception e) {
System.out.print(e.toString());
} finally {
System.out.println("关闭");
try {
os.close(); // 关闭Socket输出流
br.close(); // 关闭Socket输入流
socket.close(); // 关闭Socket
} catch (Exception e) {
}
}
}

         客户端中的ClientreadMsg类:主要书为了读取服务端发来的消息

         public class ClientreadMsg extends Thread {
  //套接字对象
 private Socket socket = null;
//有socket实例化的BufferedReader
private BufferedReader is =null;
//当前线程是否正在工作
public static boolean is_taking=false;
//通过构造函数初始化
public ClientreadMsg(Socket socket){
try{
this.socket=socket;
is=new BufferedReader(new InputStreamReader(
this.socket.getInputStream()));
}catch(Exception e){System.out.println(e.toString());}
}
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
try{
while(true){
//读取数据
String data=is.readLine();
if(data!=null&&!data.equals("")){
//如果读取到bye则结束
if(data.equalsIgnoreCase("bye")){
is_taking=true;
break;
}
System.out.println("收到服务端信息:"+data);
}
}
}catch(Exception e){System.out.println(e.toString());}finally{try{is.close();}catch(Exception e){System.out.println(e.toString());}}
}
    }

    

       Services(服务端)

          public static void main(String[] args) {
// TODO Auto-generated method stub
Socket socket = null;
PrintWriter out = null;
BufferedReader br = null;
ServerSocket server = null;
try {
// 创建一个ServerSocket在端口9086监听客户请求
server = new ServerSocket(9089);
System.out.println("服务端已经开启!!!");
// 使用accept()阻塞等待客户请求,有客户请求到来则产生一个Socket对象,并继续执行
socket = server.accept();
// 由Socket对象得到输入流,并构造相应的BufferedReader对象
//把直接流转换成字符流
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream())), true);

br = new BufferedReader(new InputStreamReader(System.in));
if (socket != null) {
System.out.println("有用户上线啦:" + socket);
out.println(socket + "已经连接上服务端!");
out.flush();
}
//新建一个读取消息的线程
new readMsgThread(server, socket).start();
while (true) {
String line = br.readLine();
if (line != null) {
out.println(line);
out.flush();
System.out.println("提示:发送到客户端的消息发送成功(正在等待客户端回复,请稍候...)!");
}
}
} catch (Exception e) {
System.out.println(e.toString());
} finally {
try {
socket.close();
server.close();
} catch (Exception e) {
}
}
}
     服务端中的readMsgThread类主要是为了读取客户端发来的消息模式一条线程,我们把读取和发送消息分开两条线程实现:

        public class readMsgThread extends Thread {
private ServerSocket server=null;
private BufferedReader is = null;
private Socket socket = null;

public readMsgThread(ServerSocket mserver,Socket socket){
System.out.println("实例化消息读取线程!");
this.server=mserver;
this.socket=socket;
try{
is = new BufferedReader(new InputStreamReader(
this.socket.getInputStream()));
}catch(Exception e){
System.out.println(e.toString());
}
}

@Override
public void run() {
// TODO Auto-generated method stub
super.run();
try{
while(true){
String data=is.readLine();
if(data!=null&&!data.equals("")){
if(data.equalsIgnoreCase("bye")){
break;
}
System.out.println("收到客户端信息:"+data);
}
}
}catch(Exception e){
System.out.println(e.toString());
}finally{
try{is.close();}catch(Exception e){System.out.println(e.toString());}
}
}
   }

    总结:其实代码的逻辑过程应该比较清楚,

    客户端发送消息(一条线程),客户端读取消息(一条线程);

    服务端发送消息(一条线程),服务端读取消息(一条线程)

                这也是多线程的简单应用。

  demo地址:http://download.csdn.net/detail/leifengpeng/8540665

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值