Java_socket程序学习01-一个客户端对一个服务器

socket开发实例1


服务端开发:

1. 在服务器,用一个端口来实例化一个 ServerSocket对象。此时,服务器就可以通过这个端口时刻监听从客户端发来的连接请求。

2.调用ServerSocket的accept方法,开始监听连接从端口上发来的连接请求。   

3.利用accept方法返回的客户端的Socket对象,进行读写IO的操作

通讯完成后,关闭打开的流和Socket对象。

package tcp;



import java.net.ServerSocket; 
import java.net.Socket;
import java.io.IOException;
import java.io.*;


public class ServerCode {


/**
* @param args
*/
//定义服务端口号为3333
    //为什么用public和static?
//为什么在外部定义公共常量
public static int portNO = 3336;    
/*
//throws IOException
//throws 是不处理,抛给。。。?
*/
public static void main(String[] args)throws IOException{

// TODO Auto-generated method stub
//ServerSocket 是java.net.ServerSocket引用的系统类
ServerSocket s = new ServerSocket(portNO);
System.out.println("The Server is start"+s);

//+s中的s就是调用serversocket的tostring方法。
//因为有toString()方法,所以print打印s时有输出地址+端口号
/*
* ServerSocket类中
*tring toString() 
*Returns the implementation address and implementation port of this socket as a String. 
*/

//Socket sk = new Socket();
//sk=s.accept();
// 阻塞,直到有客户端连接,如果客户端连接了就顺序的向下执行。
        Socket socket = s.accept();

//System.out.println("111111 ");
//与上边的两行等效
//Socket sk = s.accept();
//System.out.println("111111 ");
        try{
System.out.println("Accept the Client: " + socket);

//BufferedReader
/*java.lang.Object
java.io.Reader
    java.io.BufferedReader
  是Reader的直接子类,表示字符接收(Reader表示字符接收)
        构造方法1
    BufferedReader(Reader in) 表示接收一个Reader类的实例
        普通方法
    BufferedReader类还有普通方法readLine(),表示一次性的从缓冲区中把内容读取进来
    system.in是字节流,而Reader in为字符流,所以需要InputStreamReader把字节楼转成字符流
    BufferedReader常用法
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));接收键盘的输入
Socket的getInputStream()方法可以获得网络连接输入,同时返回一个InputStream实例

字节流通过InputStream类输入,用过OutputStream类输出。
字符流通过Reader类输入,通过Writer类输出
InputStream、OutputStream、Reader、Writer四个类都是abstact抽象类,抽象类
此四个类因为是抽象类,想要是同时,首先必须通过子类的实例化对象。
如果操作的是一个文件可以用FileOutputStream类,通过向上转型为OutputStream类实例化
OutputSteam os = new FileOutputStream("FILEDIR")
java的文件io操作
1.使用File类打开一个文件
2.通过字符流或者字节流的子类,指定输出的位置
3.进行读写
4.关闭输入输出
*/
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
/*
  * 打印流式输出信息最方便的类
 
  * PrintWriter常用的方法
  * 构造方法1
  * PrintStream(File file)通过文件File对象实例化
  * 构造方法2
  * PrintStream(OutputStream out) 通过OutputStream对象实例化,OutputStream类又是抽象类,只能接受OutputStream子类对象实例化了
  *                  | 
  *                  |-->这里其实就是指定输出位置,文件file 或者内存等等
 
  * 例如文件打印输出道文件 PrintStream ps = new PrintStream(new FileOutputStream(new File("d:"+File.separato+"test.txt")))
 
  * 普通方法
  * PrintStream printf,print(boolean b),println(boolean b)
 
  * PrintStream类,其实就是把OutputStream类重新包装一下,使其更方便
 
  * PrintWriter与PrintStream类基本相同的用法
 
  * ,  *” , true); “是boolean,在构造方法中public PrintWriter(OutputStream out,boolean autoFlush)
  * Creates a new PrintWriter from an existing OutputStream. This convenience 
  * constructor creates the necessary intermediate OutputStreamWriter, which 
  * will convert characters into bytes using the default character encoding. 
  * Parameters:
* out - An output stream
* autoFlush - A boolean; if true, the println, printf, or format methods will
  *  flush the output buffer
  */
 
 
  /*
  * 这里PrintWrite定义的输出位置是客户端,PrintWriter就是定义输出位置,和下边out.println(str);共同使用来在客户端的界面上输入str的内容
  */

PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true); 

//PrintStream out=new PrintStream(socket.getOutputStream());   //测试了也可以的

 
/*
* 此处用循环是判断输入字符后是否为bb,不是打印,结束一个循环后等待in.readLine()再次接收
* 非常好,如果我们把in.readLine()放在循环体的外部,输入内容后,循环就变成的死循环,不停的输出信息。没有in.readLine()中断。
*/ 
 
while(true){
String str = in.readLine();
if(str.equals("bb")){
break;
}  

   //服务器端显示信息
System.out.println("In Server reveived the info:"+str);
//out.println向客户端打印信息
out.println(str);         
}
         }finally{
        System.out.println("close the Server socket and the io");
        socket.close();
        s.close();
       
        }
        
}

}
这段代码的主要业务逻辑是:

1 .         在上述代码里的main函数前,我们设置了通讯所用到的端口号,为3333。

2 .         在main函数里,根据给定3333端口号,初始化一个ServerSocket对象s,该对象用来承担服务器端监听连接和提供通讯服务的功能。

3 .         调用ServerSocket对象的accept方法,监听从客户端的连接请求。当完成调用accept方法后,整段服务器端代码将回阻塞在这里,直到客户端发来connect请求。

4 .         当客户端发来connect请求,或是通过构造函数直接把客户端的Socket对象连接到服务器端后,阻塞于此的代码将会继续运行。此时服务器端将会根据accept方法的执行结果,用一个Socket对象来描述客户端的连接句柄。

5 .         创建两个名为in和out的对象,用来传输和接收通讯时的数据流。

6 .         创建一个while( true )的死循环,在这个循环里,通过in.readLine()方法,读取从客户端发送来的IO流(字符串),并打印出来。如果读到的字符串是“byebye”,那么退出while循环。

7 .         在try… catch …finally语句段里,不论在try语句段里是否发生异常,并且不论这些异常的种类,finally从句都将会被执行到。在finally从句里,将关闭描述客户端的连接句柄socket对象和ServerSocket类型的s对象。



客户端开发:


1.用服务器的IP地址和端口号实例化Socket对象。

2.调用connect方法,连接到服务器上。

3.将发送到服务器的IO流填充到IO对象里,比如BufferedReader/PrintWriter。

4.利用Socket提供的getInputStream和getOutputStream方法,通过IO流对象,向服务器发送数据流。

5. 通讯完成后,关闭打开的IO对象和Socket。

package tcp;
import java.net.*;
import java.io.*;


public class ClientCode {


/**
* @param args
*/
String name = "ly";
static int portNo=3336;
public static void main(String[] args) throws IOException{
// TODO Auto-generated method stub
/*
* Socket类的构造方法有多种,以下列举出两个来
* 构造方法1
* Socket(InetAddress address, int port) 
          * 此构造方法第一个参数需要是InetAddress类的对象
* 构造方法2
* Socket(String host, int port)

* 例子Socket socket=new Socket("127.0.0.1",30000);

*/


InetAddress addr = InetAddress.getByName("localhost");
Socket socket = new Socket(addr,portNo);


System.out.println("socket = " + socket);

BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true); 

String str = null;

while(true){
str = in.readLine();
if(str.equals("bb")){
break;
}
System.out.println(str);
out.println("My name is "+name+" "+str);
}
System.out.println("Client will be exit");
socket.close();
out.println("bb");
}

}

此客户段有个死循环,

while(true){
str = in.readLine();
if(str.equals("bb")){
break;
}
System.out.println(str);
out.println("My name is "+name+" "+str);
}

原本的目的是等带输入流,如果输入流式bb推出,如果不是就向屏幕打印,和向输出流打印,然后再循环等待下一个输入流,

但是由于server端也是有一个循环,循环体内有一个out.println(str);  [out.println向客户端打印信息],那么server端又会

把信息输出给客户端,客户端接到输入流,判断是不是”bb“,然后再打印和输出,这样就变成了死循环。改进客户端如下

package tcp;
import java.net.*;
import java.io.*;


public class ClientCode {


/**
 * @param args
 */
String name = "ly";
static int portNo=3336;
public static void main(String[] args) throws IOException{
// TODO Auto-generated method stub
/*
* Socket类的构造方法有多种,以下列举出两个来
* 构造方法1
Socket(InetAddress address, int port) 
         * 此构造方法第一个参数需要是InetAddress类的对象
         * 构造方法2
         * Socket(String host, int port)
*/
InetAddress addr = InetAddress.getByName("localhost");
Socket socket = new Socket(addr,portNo);

try{
  

System.out.println("socket = " + socket);

BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true); 

out.println("Hello Server,I am " + name);

String str = null;
str = in.readLine();
System.out.println(str);
out.println("bb");
}finally{
System.out.println("Client will be exit");
socket.close();
}

}



























































  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值