1、练习--TCP客户端并发登陆
/*
客户端通过键盘录入用户名,服务端对这个用户名进行校验。
如果该用户存在,在服务端显示XXX,已登陆。并在客户端显示XXX,欢迎光临
如果该用户不存在,在服务端显示XXX,尝试登陆。并在客户端显示XXX,该用户不存在
最多就登陆三次。
*/
import java.io.*;
import java.net.*;
class LoginClient
{
public static void main(String[] args)
{
Socket s = new Socket("192.168.0.101",10009);
BufferedReader bufr
new BufferedReader(new InputStreamReader(System.in)));
PrintWriter out = new PrintWriter(s.getOutputStream(),true);
BufferedReader bufin =
new BufferedReader(new InputStreamReader(s.getInputStream()));
for(int x = 0;x<3;x++)
{
String line = bufr.readLine();
if(line == null)
break;
out.println(line);
String info = bufin.readLine();
System.out.println("info")+info);
if(info.contains("欢迎"))
break;
}
}
}
class UserThread implements Runnable
{
private Socket s ;
UserThread(Socket s
{
this.s = s ;
}
public void run()
{
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip+"....connected");
try
{
for(int x= 0;x<3;x++)
{
BufferedReader bufin =
new BufferedReader(new InputStreamReader(s.getInputStream()));
String name = bufin.readLine();
if(name==null)
break;
BufferedReader bufr =
new BUfferedReader(new FileReader("user.txt"));
PrintWriter out = new PrintWriter(s.getOutputStream());
String line = null;
boolean flag = false;
while((line = bufr.readLine())!=null)
{
if(line.equals(name))
{
flag = true;
break;
}
}
if(flag)
{
System.out.println(name+",已经登录");
out.println(name+",欢迎光临");
break;
}
else
{
System.out.println(name+",尝试登陆");
out.println(name+",该用户不存在");
}
}
}
catch(Exception e )
{
throw new RuntimeException(ip+"校验失败");
}
}
}
class LoginServer
{
public static void main(String[] args)
{
ServerSocket ss = new ServerSocket(10009);
while(true)
{
Socket s = ss.accept();
new Thread(new UserThread(s)).start();
}
}
}
练习:浏览器客户端,自定义服务器
客户端:浏览器
服务端:自定义
import java.io.*;
import java.net.*;
class ServerDemo
{
public static void main(String[] args)
{
ServerSocket ss = new ServerSocket(10010);
Socket s = ss.accept();
System.out.println(s.getInetAddress().getHostAddress());
PrintWriter out = new PrintWriter(s.getOutputStream(),true);
out.println("客户端你好");
s.close();
ss.close();
}
}
在浏览器中输入:http://192.168.0.101:10010
telnet windows 中的远程登陆命令,可以理解为客户端软件
在这里可以在命令提示行中:
telnet 192.168.0.101 10010
这样就可以连接到我们自定义的服务器了。
练习:
客户端:浏览器
服务端:Tomcat服务器。
练习:
客户端:自定义
服务端:Tomcat服务器
/*
import java.io.*;
import java.net.*;
class ServerDemo
{
public static void main(String[] args)
{
ServerSocket ss = new ServerSocket(10010);
Socket s = ss.accept();
System.out.println(s.getInetAddress().getHostAddress());
InputStream in = s.getInputStream();
byte[] buf = new byte[1024];
int len = in.read(buf);
System.out.println(len+"........"+new String(buf,0,len));
PrintWriter out = new PrintWriter(s.getOutputStream(),true);
out.println("客户端你好");
s.close();
ss.close();
}
}
*/
自定义的客户端
import java.io.*;
import java.net.*;
class MyIE
{
public static void main(String[] args) throws Exception
{
Socket s = new Socket("192.168.0.101",8080);
PrintWriter out = new PrintWriter(s.getOutputStream(),true);
//GET 命令,表示访问GET后面的内容
out.println("GET / myweb/demo.html HTTP/1.1");
//
out.println("Accept: */*");
//所接受的语言
out.println("Accept-Language:zh-cn");
//访问的主机与端口号
out.println("Host:192.168.0.101:10010");
out.println("Connection:Keep-Alive");//注意该行下面要有两空行
out.println();
out.println();
BufferedReader bufr =
new BufferedReader(new InputStreamReader(s.getInputStream()));
String line = null;
while((line = bufr.readLine())!=null)
{
System.out.println(line);
}
s.close();
}
}
练习:自定义界面浏览器
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
class MyIEByGUI
{
private Frame f;
private TextField tf;
private Button but;
private TextArea ta;
private Dialog d;
private Label lab;
private Button okBut;
MyIEByGUI ()
{
init();
}
public void init()
{
f = new Frame("my window");
f.setBounds(300,100,600,500);
f.setLayout(new FlowLayout());
tf = new TextField(60);
but = new Button("转到");
ta = new TextArea(25,70);
d = new Dialog(f,“提示信息-self",true);
d.setBounds(400,200,240,150);
d.setLayout(new FlowLayout());
lab = new Label();
okBut = new Button("确定");
d.add(lab);
d.add(okBut);
f.add(tf);
f.add(but);
f.add(ta);
myEvent();
f.setVisible(true);
}
private void myEvent()
{
okBut.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
d.setVisible(false);
}
});
d.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
d.setVisible(false);
}
});
tf.addKeyListener(new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode()==KeyEvent.VK_ENTER)
showDir();
}
});
but.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
showDir();
}
});
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
}
private void showDir()
{
ta.setText("");
String url = tf.getText();//http://192.168.0.101:8080/myweb/demo.html
int index1 = url.indexOf("//")+2;
int index2 = url.indexOf("/",index1);
String str =url.substring(index1,index2);
Stirng[] arr = str.split(":");
String host = arr[0];
String port = arr[1];
String path = rul.substring(index2);
// ta.setText(str+" "+path);/*String dirPath = tf.getText();File dir = new File(dirPath);if(dir.exists()&&dir.isDirectory()){ta.setText("");String[] names = dir.list();for(String name:names){ta.apend(name+"\r\n");}}else{String info = "您输入的信息"+dirPath+"是错误的,请重新");lab.setText(info);d.setVisible(true);}*/Socket s = new Socket(host,post);
PrintWriter out = new PrintWriter(s.getOutputStream(),true);
//GET 命令,表示访问GET后面的内容
out.println("GET / myweb/demo.html HTTP/1.1");
//
out.println("Accept: */*");
//所接受的语言
out.println("Accept-Language:zh-cn");
//访问的主机与端口号
out.println("Host:"+host+":"+port);
out.println("Connection:Keep-Alive");//注意该行下面要有两空行out.println();
out.println();
BufferedReader bufr =
new BufferedReader(new InputStreamReader(s.getInputStream()));
String line = null;while((line = bufr.readLine())!=null)
{System.out.println(line);
}
s.close();
}
public static void main(String[] args) throws Exception
{
new MyIEByGUI();
}
}
2、URL:统一资源定位符
构造方法:
URL(String spec):根据String表示形式创建URL对象
URL(String protocol,String host ,int port,String file):根据指定protocol(协议), host ,port和file创建URL对象
class URLDemo
{
public static void main(String[] args) throws MalformedURLException
{
URL url = new URL("http://192.168.0.101:8080/meweb/demo.html?name=haha&age=39");
sop(url.getProtocol());//协议名http
sop(url.getHost());//主机名192.168.0.101
sop(url.getPort());//端口号8080,没有指定端口时,返回-1(http://192.168.0.101/meweb/demo.html)
sop(url.getPath());//路径meweb/demo.html
sop(url.getFile());//文件名meweb/demo.html?name=haha&age=39
sop(url.getQuery());//查询部name=haha&age=39
//如果没有指定端口,则有如下代码,默认80
// int port = getPort();
// if(port==-1)
// prot=80;
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
方法:public URLConnection openConnection() throws IOException
该方法返回一个URLConnection对象,它表示到URL所引用的远程对象的连接
类:public Abstract class URLConnection extends Object
该抽象类是所有类的超类,它代表应用程序和URL之间的通信链接,此类的实例可用于读取和写入此URL应用的资源。通常,创建一个到URL的连接需要几个步骤
1、通过在URL上调用openConnection方法创建连接对象
2、处理设置参数和一般请求属性
3、使用connect方法建立到远程对象的实际链接
4、远程对象变为可用,远程对象的头字段和内容变为可访问
import java.net.*;
import java.io.*;
class URLConnectionDemo
{
public static void main(String[] args) throws Exception
{
/*
用Socket做的连接都是在传输层,而URL做的连接在应用层(没有响应头),
*/
URL url = new URL("http://192.168.0.101:8080/meweb/demo.html");
URLConnection conn = url.openConnection();
sop(conn);
InputStream in = conn.getInputStream();
byte[] buf = new byte[1024];
int len = in.read(buf);
sop(new String(buf,0,len));
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
用URl方式替代socket,自定义浏览器重写;主要目的是去掉响应头
响应头:
/*
out.println("GET / myweb/demo.html HTTP/1.1");
//
out.println("Accept: */*");
//所接受的语言
out.println("Accept-Language:zh-cn");
//访问的主机与端口号
out.println("Host:192.168.0.101:10010");
out.println("Connection:Keep-Alive");//注意该行下面要有两空行
*/
原理:服务端在返回给客户端的时候,内容包括响应头和数据内容,socket传输层接收响应头和数据,因此用socket做的浏览器会显示响应头;而URL是在应用层的,在传输层接收了响应头和数据,在应用层解析了响应头,因此显示出来的只有数据内容而没有响应头
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
class MyIEByGUI
{
private Frame f;
private TextField tf;
private Button but;
private TextArea ta;
private Dialog d;
private Label lab;
private Button okBut;
MyIEByGUI ()
{
init();
}
public void init()
{
f = new Frame("my window");
f.setBounds(300,100,600,500);
f.setLayout(new FlowLayout());
tf = new TextField(60);
but = new Button("转到");
ta = new TextArea(25,70);
d = new Dialog(f,“提示信息-self",true);
d.setBounds(400,200,240,150);
d.setLayout(new FlowLayout());
lab = new Label();
okBut = new Button("确定");
d.add(lab);
d.add(okBut);
f.add(tf);
f.add(but);
f.add(ta);
myEvent();
f.setVisible(true);
}
private void myEvent()
{
okBut.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
d.setVisible(false);
}
});
d.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
d.setVisible(false);
}
});
tf.addKeyListener(new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode()==KeyEvent.VK_ENTER)
showDir();
}
});
but.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
showDir();
}
});
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
}
private void showDir()
{
ta.setText("");
String url = tf.getText();//http://192.168.0.101:8080/myweb/demo.html
URL url = new URL(url);
URLConnection conn = url.openConnection();
sop(conn);
InputStream in = conn.getInputStream();
byte[] buf = new byte[1024];
int len = in.read(buf);
ta.setText(new String(buf,0,len));
}
public static void main(String[] args) throws Exception
{
new MyIEByGUI();
}
}
3、类public abstract class SocketAddress extends Object implements Serializable
此类 表示不带任何协议附件的Socket Address ,作为一个抽象类,应通过特定的、协议相关的实现为其创建子类,它提供不可变对象,供套接字用于绑定、连接或用作返回值。
直接已知子类:InetSocketAddress
public class InetSocketAddress extends SocketAddress
此类实现IP套接字地址(IP地址+端口号).它还可以是一个对(主机名+端口号),在此情况下,将尝试解析主机名。如果解析失败,则该地址将被视为未解析地址,但是其在某些情形下仍然可以使用,比如通过代理连接。
它提供不可变对象,供套接字用于绑定、连接或用作返回值
通配符是一个特殊的本地IP地址,它通常表示”任何“,只能用于bind操作
4、类ServerSocket的构造方法
ServerSocket(int port ,int backlog):port,端口号;backlog,表示队列的最大长度,也就是同时在线人数。比如,backlog是3,那么只能允许3个人同时连接,第四个就连接不上
5、域名解析:
http://192.168.0.101:8080/myweb/demo.html
想要将主机名翻译成IP地址,需要域名解析,DNS
首先找域名解析服务器(该服务器上存储的都是,主机名与地址的映射关系,如 sina 19.19.19.19)
根据域名获得IP地址,然后读取地址找到网站
注意:本机地址:http://127.0.0.1:8080 与http://localhost:8080 是对应的,其 对应关系在
C:\Windows\System32\drivers\etc
其内容为:
# Copyright (c) 1993-2009 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
# 102.54.94.97 rhino.acme.com # source server
# 38.25.63.10 x.acme.com # x client host
# localhost name resolution is handled within DNS itself.
# 127.0.0.1 localhost
# ::1 localhost
在这里可以修改localhost,例如myhost,那么以后就可以使用myhost了,修改后localhost就不能用了。
我们在访问主机的时候,先访问本地 C:\Windows\System32\drivers\etc 是否有该主机名,如果有就访问其对应的地址,如果没有就访问网上的网站。
如果我们在文件内配置上:13.12.11.10
www.sina.com.cn
我们再访问新浪的时候,会先找本地文件中查找,找到13.12.11.10,则直接找到网站,就不用再走DNS服务器了。
另一种用法;让付费软件更新失败
付费软件一般都是,在启动软件的时候,软件会自动连接网站提供一些信息,该信息就包括免费期信息,如果免费期到了,就需要付费了,这时我们可以不让该软件连接网站,就把该网站的域名对应本机地址,就是在该文件上设置:
如:127.0.0.1
www.myelipse.com 这样:启动软件,找到该文件,然后访问127.0.0.1就无法连接到其网站了