j2se----TCP---socket

ServerSocket -----相当于114查号台的 总机,他是专门接电话进来的
服务端的Socket----相当于114查号台的座机,当总机接到电话后,就分配给一个空闲的座机来接听

客户端的Socket----相当于 电话

建立连接的两个Socket在一个单独的线程(由服务器创建)上对话

ServerSocket的构造函数:
public ServerSocket();//他不能直接使用,还需要调用一个bind方法设置端口号

public ServerSocket(int port); //如果端口号是0,那么系统将制定一个没被其他程序使用的端口号
public ServerSocket(int port ,int backlog); //backlog(backlogin)用于制定在服务器很忙的时候,他可以与之保持请求的等待客户数量,如果没有制定,那么默认的数量是50

public ServerSocket(int port ,int backlog ,InetAddress binAddr);//这个适合于计算机上有多个网卡和多个ip的情况

close();//他需要关闭哈


Socket的构造函数
public Socket(); //如果想使用同一个Socket去轮训多个服务器,就可以用这个,他必须和一个connect()以前连用
public Socket(String host ,int port);  //接收字符串格式的ip地址
public Socket(InetAddress address,int port); //接收ip地址类

public Socket(String host,int port,InetAddress localAddress,int localPort);
public Socket(InetAddress address,int port,InetAddress localAddress,int localPort); //这两个是上面两个加了本地ip,很少用,除非有多块网卡


当客户端和服务端的Socket建立专线连接以后,他们通过字节流的形式进行数据交换
getInputStream    getOutputStream

注意 : ServerSocket ss = new ServerSocket(8001);
       Socket s  =  ss.accept();  //这里如果8001在分配前就被其他程序占用,那么ss.accept()不会被阻塞,因为绑定失败了,而所谓的阻塞其实也就是个内循环

注意关闭的顺序

ips.close();
ops.close();
s.close();
ss.close(); //先关闭输入输出流,在关闭座机,在关闭总机

服务器端代码这样写好吗?

InputStream ips = s.getInputStream();
byte[] buf = new byte[1024];
int len = ips.read(buf);
...
ips.close();
ops.close();
s.close();
ss.close();

注意:这样不好。。因为不管ips读到了多少个数据,他都会返回,所以我们不能假象客服端程序一次就发送了全部的数据,说不定他可能只先发了一个字节然后再发送。。。。

服务器端的程序应该这样写:
InputStream ips = s.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(ips));
String s = null;
while((s=br.readLine())!=null){
   syso(s);
}

br.close();
s.close();
ss.close();       

如果要想让服务器接受好多客户端的连接请求,怎么办?

只能循环调用 ss.accept();//方法

ServerSocket ss = new ServerSocket();
boolean isRunning = true;
while(isRunning){ //这里要写成isRunning 不能直接写成true,因为直接写成true,那么编译器就会认为这个循环式无限循环,所以他或说ss.close()这个方法无法到达,而我们把它换成一个变量后,编译器就完全不关心这个值了,因为他是变量嘛,既然可变就有可能是true,有可能是false;
  Socket s = ss.accept();
  new Thread(new Server(s)).start();
  
}
ss.close();

public class Server implement Runnable{
  private  Socket s ;
  public Server(Socket s ){
     this.s = s; 
  }
   public void run(){
       
       BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
       PrintWriter pw = new PrintWriter(s.getOutputStream(),true);//因为包装了输出流,所以他当然也是向输出流中写啦,不过这个东西的好处是他写一行数据时的换行符是平台相关的,而过时的PrintStream写的换行符是平台无关的。。。这里是true表明自动flush
       boolean isRunning = false;
        while(isRunning ){
          //这个Socket也是不停的结束数据的哦
          String strLine = br.readLine();
        strLine = ((new StringBuffer(strLine)).reverse()).toString();//注意:StringBuffer的reverse方法可以将字符串方向排列
           pw.println(strLine);
        //  pw.flush(); //注意这个时候flush是有用的,因为在死循环中pw是不会得到关闭的,所以这时候flush方法就有用了,在没法关闭pw的时候需要用flush来清空缓冲区,但是这里没有flush方法啊。。怎么办。。。一定一共了自动清空的设置
        }
        br.close();
         pw.close();
   }
}

注意:我们如果用telnet 在命令行输入 abc然后发现输入错误,我们按了个退格键,然后再输入d ,那么在服务器端接收到的是  abc{backspace}d ,这个东西在屏幕上显示的效果为abd, 而实际是5个字符哈,而反向后的情况是d{backspace}cba,那么显示的效果是cba....张孝祥想出来的哈。。。太厉害了

你可能感兴趣的:(thread,socket,J2SE)