java 基础复习 网络编程

网络编程






网络通讯的3要素是IP地址,端口号和传送协议。
IP地址用以表示网络中的设备,每个设备都有自己唯一的IP地址。本地回环地址是127.0.0.1,同常对应的默认主机名称是localhost。192.168.0.0 用于公网  192.168.0.255用于广播
端口号指的是逻辑端口,每个软件在运行时,系统都会分配给它一个未使用的端口号。
端口号的范围是0~65535,通常0~1024用于系统使用或保留端口
传输协议就是通讯规则,双方发送给对方的数据信息符合指定的传输协议,就可以被对方识别。
如果发送端和接收端安装了共同的网络数据协议,并明确了接收端的IP地址和端口号,就可以将数据发送给接收端。


网络参考模型
OSI参考模型,和TCP/IP参考模型是比较常见的两种网络参考模型。做网络编程,主要涉及的是网际层和传输层。传输层最常见的是TCP和UDP,网际层最常见的是IP,http、ftp是应用层协议。并且应用层基于传输层。

包java.net 用于描述网络
包java.net 用于描述网络,其中有操作IP地址的 InetAddress类 ;有创建UDP服务的 类DatagramSocket,类DatagramPacket 等;有创建TCP服务客户端的 类Socket,服务端的 类ServerSocket等。操作网页的 类URL等


类InetAddress没有可见的构造函数,方法如下

方法摘要
 boolean equals(Object obj) 
          将此对象与指定对象比较。
重要 byte[] getAddress() 
          返回此 InetAddress 对象的原始 IP 地址。
static InetAddress[]
getAllByName(String host) 
          在给定主机名的情况下,根据系统上配置的名称服务返回其 IP 地址所组成的数组。
重要 static InetAddress
getByAddress(byte[] addr) 
          在给定原始 IP 地址的情况下,返回 InetAddress 对象。
重要 static InetAddress
getByAddress(String host, byte[] addr) 
          根据提供的主机名和 IP 地址创建 InetAddress。
重要 static InetAddress
getByName(String host) 
          在给定主机名的情况下确定主机的 IP 地址。
 String
getCanonicalHostName() 
          获取此 IP 地址的完全限定域名。
常用 String
getHostAddress() 
          返回 IP 地址字符串(以文本表现形式)。
常用 String
getHostName() 
          获取此 IP 地址的主机名。
重要 static InetAddress
getLocalHost() 
          返回本地主机。
 int hashCode() 
          返回此 IP 地址的哈希码。
 boolean isAnyLocalAddress() 
          检查 InetAddress 是否是通配符地址的实用例行程序。
 boolean isLinkLocalAddress() 
          检查 InetAddress 是否是链接本地地址的实用例行程序。
 boolean isLoopbackAddress() 
          检查 InetAddress 是否是回送地址的实用例行程序。
 boolean isMCGlobal() 
          检查多播地址是否具有全局域的实用例行程序。
 boolean isMCLinkLocal() 
          检查多播地址是否具有链接范围的实用例行程序。
 boolean isMCNodeLocal() 
          检查多播地址是否具有节点范围的实用例行程序。
 boolean isMCOrgLocal() 
          检查多播地址是否具有组织范围的实用例行程序。
 boolean isMCSiteLocal() 
          检查多播地址是否具有站点范围的实用例行程序。
 boolean isMulticastAddress() 
          检查 InetAddress 是否是 IP 多播地址的实用例行程序。
 boolean isReachable(int timeout) 
          测试是否可以达到该地址。
 boolean isReachable(NetworkInterface netif, int ttl, int timeout) 
          测试是否可以达到该地址。
 boolean isSiteLocalAddress() 
          检查 InetAddress 是否是站点本地地址的实用例行程序。
重要 String
toString() 
          将此 IP 地址转换为 String。




类DatagramSocket


构造方法摘要
常用 DatagramSocket()   
用于发送端或接收端,倘用作发送端,在DatagramSocket中指定IP和端口;倘用于接收端,使用connect()方法连接发送端
          构造数据报套接字并将其绑定到本地主机上任何可用的端口。
protected DatagramSocket(DatagramSocketImpl impl) 
          创建带有指定 DatagramSocketImpl 的未绑定数据报套接字。
  DatagramSocket(int port) 
          创建数据报套接字并将其绑定到本地主机上的指定端口。
  DatagramSocket(int port, InetAddress laddr) 用于发送端
          创建数据报套接字,将其绑定到指定的本地地址。
  DatagramSocket(SocketAddress bindaddr) 
          创建数据报套接字,将其绑定到指定的本地套接字地址。


方法摘要
 void bind(SocketAddress addr) 
          将此 DatagramSocket 绑定到特定的地址和端口。
常用   void close()
          关闭此数据报套接字。
常用 void connect(InetAddress address, int port) 
          将套接字连接到此套接字的远程地址。
 void connect(SocketAddress addr) 
          将此套接字连接到远程套接字地址(IP 地址 + 端口号)。
 void disconnect() 
          断开套接字的连接。
 boolean getBroadcast() 
          检测是否启用了 SO_BROADCAST。
 DatagramChannel
getChannel() 
          返回与此数据报套接字关联的唯一 DatagramChannel 对象(如果有)。
常用 InetAddress
getInetAddress() 
          返回此套接字连接的地址。
常用 InetAddress
getLocalAddress() 
          获取套接字绑定的本地地址。
常用 int getLocalPort() 
          返回此套接字绑定的本地主机上的端口号。
 SocketAddress
getLocalSocketAddress() 
          返回此套接字绑定的端点的地址,如果尚未绑定则返回 null。
常用 int getPort() 
          返回此套接字的端口。
 int getReceiveBufferSize() 
          获取此 DatagramSocket 的 SO_RCVBUF 选项的值,该值是平台在 DatagramSocket 上输入时使用的缓冲区大小。
 SocketAddress
getRemoteSocketAddress() 
          返回此套接字连接的端点的地址,如果未连接则返回 null。
 boolean getReuseAddress() 
          检测是否启用了 SO_REUSEADDR。
 int getSendBufferSize() 
          获取此 DatagramSocket 的 SO_SNDBUF 选项的值,该值是平台在 DatagramSocket 上输出时使用的缓冲区大小。
 int getSoTimeout() 
          获取 SO_TIMEOUT 的设置。
 int getTrafficClass() 
          为从此 DatagramSocket 上发送的包获取 IP 数据报头中的流量类别或服务类型。
 boolean isBound() 
          返回套接字的绑定状态。
 boolean isClosed() 
          返回是否关闭了套接字。
 boolean isConnected() 
          返回套接字的连接状态。
重要 void receive(DatagramPacket p) 
          从此套接字接收数据报包。
重要 void send(DatagramPacket p) 
          从此套接字发送数据报包。
 void setBroadcast(boolean on) 
          启用/禁用 SO_BROADCAST。
static void setDatagramSocketImplFactory(DatagramSocketImplFactory fac) 
          为应用程序设置数据报套接字实现工厂。
 void setReceiveBufferSize(int size) 
          将此 DatagramSocket 的 SO_RCVBUF 选项设置为指定的值。
 void setReuseAddress(boolean on) 
          启用/禁用 SO_REUSEADDR 套接字选项。
 void setSendBufferSize(int size) 
          将此 DatagramSocket 的 SO_SNDBUF 选项设置为指定的值。
 void setSoTimeout(int timeout) 
          启用/禁用带有指定超时值的 SO_TIMEOUT,以毫秒为单位。
 void setTrafficClass(int tc) 
          为从此 DatagramSocket 上发送的数据报在 IP 数据报头中设置流量类别 (traffic class) 或服务类型八位组 (type-of-service octet)。


类DatagramPacket    
final修饰,构造方法中,只接收字节数组 


构造方法摘要
DatagramPacket(byte[] buf, int length) 
          构造 DatagramPacket,用来接收长度为 length 的数据包。
常用
DatagramPacket(byte[] buf, int length, InetAddress address, int port) 
          构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
DatagramPacket(byte[] buf, int offset, int length) 
          构造 DatagramPacket,用来接收长度为 length 的包,在缓冲区中指定了偏移量。
DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port) 
          构造数据报包,用来将长度为 length 偏移量为 offset 的包发送到指定主机上的指定端口号。
DatagramPacket(byte[] buf, int offset, int length, SocketAddress address) 
          构造数据报包,用来将长度为 length 偏移量为 offset 的包发送到指定主机上的指定端口号。
DatagramPacket(byte[] buf, int length, SocketAddress address) 
          构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
  
方法摘要
重要 InetAddress
getAddress() 
          返回某台机器的 IP 地址,此数据报将要发往该机器或者是从该机器接收到的。
重要 byte[] getData() 
          返回数据缓冲区。
重要 int getLength() 
          返回将要发送或接收到的数据的长度。
 int getOffset() 
          返回将要发送或接收到的数据的偏移量。
常用 int getPort() 
          返回某台远程主机的端口号,此数据报将要发往该主机或者是从该主机接收到的。
SocketAddress
getSocketAddress() 
          获取要将此包发送到的或发出此数据报的远程主机的 SocketAddress(通常为 IP 地址 + 端口号)。
 void setAddress(InetAddress iaddr) 
          设置要将此数据报发往的那台机器的 IP 地址。
 void setData(byte[] buf) 
          为此包设置数据缓冲区。
 void setData(byte[] buf, int offset, int length) 
          为此包设置数据缓冲区。
 void setLength(int length) 
          为此包设置长度。
 void setPort(int iport) 
          设置要将此数据报发往的远程主机上的端口号。
 void setSocketAddress(SocketAddress address) 
          设置要将此数据报发往的远程主机的 SocketAddress(通常为 IP 地址 + 端口号)。




UDP服务的建立——UDP聊天
UDP的特点面向无连接,不可靠,速度快,发送的数据报包大小在64K内


/*本程序已测试,OK*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;


import IO.so;


/*
* 收和发同时进行,所以收和发在不同的线程中
 * 
 * 接收端
 * 键盘录入:键盘录入字节流——>转换字符流——>字符流缓冲区——>循环读取并储存缓冲区的字符——>字节流
 * 1DatagramSocket——2DatagramPacket(传入数据并明确接收端的IP地址和端口)——3发送
 * 2要注意
 * 因为定义的字节数组是读取的字符转换而来,所以,传入的时候应该传入字节数组的长度
 * 另外要注意getByName()的用法
 * 
 * 接收端
 * 建立端点
 * DatagramSocket(设置端点)—>读取发送端发送来的信息——>拆包
 * 
 * */
class UDPChatS implements Runnable {
private DatagramSocket ds ;
public UDPChatS(DatagramSocket ds) {
super();
this.ds = ds;
}
public void run()
{
//读取键盘录入
BufferedReader br = 
new BufferedReader(new InputStreamReader(System.in));
try {
String line = null ;
//接受键盘录入的数据
while ((line = br.readLine())!=null) {
if (line.equals("886"))
break ;
byte[] buf = line.getBytes();
//数据封包
DatagramPacket dp = 
new DatagramPacket(buf,buf.length, InetAddress.getByName("192.168.0.100"),10060);
//发送数据包
ds.send(dp);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//关闭键盘录入流
try {
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//关闭服务端
ds.close();
}
}
class UDPChatR implements Runnable{
private DatagramSocket ds ;
public UDPChatR(DatagramSocket ds) {
super();
this.ds = ds;
}
public void run() {
while(true){
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
try {
ds.receive(dp);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String data = new String (buf,0,dp.getLength());
String ip = dp.getAddress().getHostAddress();
so.p(ip+": "+data);
}
}
}
class ChatDemo{
public static void main(String[] args){
DatagramSocket dsSend = null ;
DatagramSocket dsRece = null;
try {
dsSend = new DatagramSocket();
dsRece = new DatagramSocket(10061);
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
UDPChatR sChatR = new UDPChatR(dsRece);
UDPChatS sChatS = new UDPChatS(dsSend);
new Thread(sChatR).start();
new Thread(sChatS).start();
}
}


TCP服务的建立
类Socket
构造方法摘要
Socket() 
          通过系统默认类型的 SocketImpl 创建未连接套接字
常用 Socket(InetAddress address, int port) 
          创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
已过时 Socket(InetAddress host, int port, boolean stream) 
          已过时。 Use DatagramSocket instead for UDP transport.
  Socket(InetAddress address, int port, InetAddress localAddr, int localPort) 
          创建一个套接字并将其连接到指定远程地址上的指定远程端口。
  Socket(Proxy proxy) 
          创建一个未连接的套接字并指定代理类型(如果有),该代理不管其他设置如何都应被使用。
protected Socket(SocketImpl impl) 
          使用用户指定的 SocketImpl 创建一个未连接 Socket。
重要 Socket(String host, int port) 
          创建一个流套接字并将其连接到指定主机上的指定端口号。


已过时 Socket(String host, int port, boolean stream) 
          已过时。 使用 DatagramSocket 取代 UDP 传输。
  Socket(String host, int port, InetAddress localAddr, int localPort) 
          创建一个套接字并将其连接到指定远程主机上的指定远程端口。




  
方法摘要
 void bind(SocketAddress bindpoint) 
          将套接字绑定到本地地址。
 void close() 
          关闭此套接字。
void connect(SocketAddress endpoint) 
          将此套接字连接到服务器。
 void connect(SocketAddress endpoint, int timeout) 
          将此套接字连接到服务器,并指定一个超时值。
 SocketChannel
getChannel() 
          返回与此数据报套接字关联的唯一 SocketChannel 对象(如果有)。
InetAddress
getInetAddress() 
          返回套接字连接的地址。
InputStream
getInputStream() 
          返回此套接字的输入流。
 boolean getKeepAlive() 
          测试是否启用 SO_KEEPALIVE。
 InetAddress
getLocalAddress() 
          获取套接字绑定的本地地址。
 int getLocalPort() 
          返回此套接字绑定到的本地端口。
 SocketAddress
getLocalSocketAddress() 
          返回此套接字绑定的端点的地址,如果尚未绑定则返回 null。
 boolean getOOBInline() 
          测试是否启用 OOBINLINE。
OutputStream
getOutputStream() 
          返回此套接字的输出流。
 int getPort() 
          返回此套接字连接到的远程端口。
 int getReceiveBufferSize() 
          获取此 Socket 的 SO_RCVBUF 选项的值,该值是平台在 Socket 上输入时使用的缓冲区大小。
 SocketAddress
getRemoteSocketAddress() 
          返回此套接字连接的端点的地址,如果未连接则返回 null。
 boolean getReuseAddress() 
          测试是否启用 SO_REUSEADDR。
 int getSendBufferSize() 
          获取此 Socket 的 SO_SNDBUF 选项的值,该值是平台在 Socket 上输出时使用的缓冲区大小。
 int getSoLinger() 
          返回 SO_LINGER 的设置。
 int getSoTimeout() 
          返回 SO_TIMEOUT 的设置。
 boolean getTcpNoDelay() 
          测试是否启用 TCP_NODELAY。
 int getTrafficClass() 
          为从此 Socket 上发送的包获取 IP 头中的流量类别或服务类型。
 boolean isBound() 
          返回套接字的绑定状态。
 boolean isClosed() 
          返回套接字的关闭状态。
 boolean isConnected() 
          返回套接字的连接状态。
 boolean isInputShutdown() 
          返回是否关闭套接字连接的半读状态 (read-half)。
 boolean isOutputShutdown() 
          返回是否关闭套接字连接的半写状态 (write-half)。
 void sendUrgentData(int data) 
          在套接字上发送一个紧急数据字节。
 void setKeepAlive(boolean on) 
          启用/禁用 SO_KEEPALIVE。
 void setOOBInline(boolean on) 
          启用/禁用 OOBINLINE(TCP 紧急数据的接收者) 默认情况下,此选项是禁用的,即在套接字上接收的 TCP 紧急数据被静默丢弃。
 void setPerformancePreferences(int connectionTime, int latency, int bandwidth) 
          设置此套接字的性能偏好。
 void setReceiveBufferSize(int size) 
          将此 Socket 的 SO_RCVBUF 选项设置为指定的值。
 void setReuseAddress(boolean on) 
          启用/禁用 SO_REUSEADDR 套接字选项。
 void setSendBufferSize(int size) 
          将此 Socket 的 SO_SNDBUF 选项设置为指定的值。
static void setSocketImplFactory(SocketImplFactory fac) 
          为应用程序设置客户端套接字实现工厂。
 void setSoLinger(boolean on, int linger) 
          启用/禁用具有指定逗留时间(以秒为单位)的 SO_LINGER。
 void setSoTimeout(int timeout) 
          启用/禁用带有指定超时值的 SO_TIMEOUT,以毫秒为单位。
 void setTcpNoDelay(boolean on) 
          启用/禁用 TCP_NODELAY(启用/禁用 Nagle 算法)。
 void setTrafficClass(int tc) 
          为从此 Socket 上发送的包在 IP 头中设置流量类别 (traffic class) 或服务类型八位组 (type-of-service octet)。
void shutdownInput() 
          此套接字的输入流置于“流的末尾”。
void shutdownOutput() 
          禁用此套接字的输出流。
String
toString() 
          将此套接字转换为 String。


构造方法摘要
ServerSocket() 
          创建非绑定服务器套接字。
ServerSocket(int port) 
          创建绑定到特定端口的服务器套接字。
ServerSocket(int port, int backlog) 
          利用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口号。
ServerSocket(int port, int backlog, InetAddress bindAddr) 
          使用指定的端口、侦听 backlog 和要绑定到的本地 IP 地址创建服务器。
  
方法摘要
Socket
accept() 
          侦听并接受到此套接字的连接。
 void bind(SocketAddress endpoint) 
          将 ServerSocket 绑定到特定地址(IP 地址和端口号)。
 void bind(SocketAddress endpoint, int backlog) 
          将 ServerSocket 绑定到特定地址(IP 地址和端口号)。
void close() 
          关闭此套接字。
 ServerSocketChannel
getChannel() 
          返回与此套接字关联的唯一 ServerSocketChannel 对象(如果有)。
InetAddress
getInetAddress() 
          返回此服务器套接字的本地地址。
 int getLocalPort() 
          返回此套接字在其上侦听的端口。
 SocketAddress
getLocalSocketAddress() 
          返回此套接字绑定的端点的地址,如果尚未绑定则返回 null。
 int getReceiveBufferSize() 
          获取此 ServerSocket 的 SO_RCVBUF 选项的值,该值是将用于从此 ServerSocket 接受的套接字的建议缓冲区大小。
 boolean getReuseAddress() 
          测试是否启用 SO_REUSEADDR。
 int getSoTimeout() 
          获取 SO_TIMEOUT 的设置。
protected  void implAccept(Socket s) 
          ServerSocket 的子类使用此方法重写 accept() 以返回它们自己的套接字子类。
 boolean isBound() 
          返回 ServerSocket 的绑定状态。
 boolean isClosed() 
          返回 ServerSocket 的关闭状态。
 void setPerformancePreferences(int connectionTime, int latency, int bandwidth) 
          设置此 ServerSocket 的性能首选项。
 void setReceiveBufferSize(int size) 
          为从此 ServerSocket 接受的套接字的 SO_RCVBUF 选项设置默认建议值。
 void setReuseAddress(boolean on) 
          启用/禁用 SO_REUSEADDR 套接字选项。
static void setSocketFactory(SocketImplFactory fac) 
          为应用程序设置服务器套接字实现工厂。
 void setSoTimeout(int timeout) 
          通过指定超时值启用/禁用 SO_TIMEOUT,以毫秒为单位。
String
toString() 
          作为 String 返回此套接字的实现地址和实现端口。


1TCP复制文件
2TCP并发上传图片
3TCP并发登录
import java.io.*;
import java.net.*;
import java.util.Date;
//tcp并发上传图片
//tcp的特点,面向连接,可靠,效率稍低,数据大量传输


/*
 * 客户端
 * 图片写到流
 * socket流读取流里的图片数据
 * 发送到服务端
 * 
 * */
//客户端
class UploadPicC implements Runnable{
private File file ;

public UploadPicC(File file) {
super();
this.file = file;
}


@Override
public void run() {
// TODO Auto-generated method stub
try {
OutputStream os = null;
Socket socket = null ;
try {
socket = new Socket("192.168.0.100",10070);
os = socket.getOutputStream();
} catch (UnknownHostException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
FileInputStream f = new FileInputStream(file);

byte[] buf = new byte[1024];

try {

int len=0;
byte[] b = new byte[1024];
while((len = f.read(buf))!=-1)//这里判断的是-1
{
os.write(b,0,len);
}
socket.shutdownOutput();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();//这里要关流,要不然服务端会报异常
}
try {
BufferedReader br = 
new BufferedReader(new InputStreamReader(socket.getInputStream()));
String str = br.readLine();
so.p(str);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}
//服务端:
/* 建立一个文件写入流
 * 接受图片得到socket的读取刘,利用读写流的write方法将数据写到,已经上传成功
 * */
class UploadPicS implements Runnable{


ServerSocket ss ;

public UploadPicS(ServerSocket ss) {
super();
this.ss = ss;
}


@Override
public void run() {
// TODO Auto-generated method stub
try {
Socket socket = ss.accept();
String ip  = socket.getInetAddress().getHostAddress();
so.p(ip+"......connected");

FileOutputStream fos = new FileOutputStream("c:\\1_1.jpg");

InputStream in = socket.getInputStream();

//向客户端反馈信息
PrintWriter  pw =
new PrintWriter(socket.getOutputStream(),true);
Date d = new Date();

byte[] b =new byte[1024];
int len = 0;
//循环读取socket输入流中的数据

while ((len = in.read(b))!=-1) {
//将数据写到目标文件
fos.write(b, 0, len);
}
so.p(ip+":上传成功");

pw.write("在    "+d.toString()+"  上传成功");
pw.close();//要关流  ,要不然客户端会出异常
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}
class TCP_UploadPic {
 
public static void main(String[] args) {
ServerSocket ss;
try {
ss = new  ServerSocket(10070);
UploadPicS s = new UploadPicS(ss);
new Thread(s).start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
}
3TCP并发登录
//TCP客户端并发登录




//手法:定义标记flag
/*
客户端通过键盘录入用户名
服务端对这个用户名进行校验


如果该用户存在,在服务端显示xxx,已登录
并在客户端显示xxx,欢迎光临


如果该用户存在,在服务端显示xxx,尝试登录
如果客户端显示xxx,该用户不存在


最多登录3次


*/
/*
1读取键盘录入
2将键盘录入的信息传入流InputStream
3接收服务端发来的信息
*/
import java.io.*;
import java.net.*;
class LoginC  
{
public static void main(String[] args) throws Exception
{
Socket s = new Socket("192.168.0.100",10050);//如果是空“”,是为本机
//键盘录入流
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();//键盘录入时,按ctrl+c是空,返回-1

//键盘录入时,按ctrl+c是空,返回-1,说明客户端不想录入了,就结束了
if(line == null)
break ;
//将录入内容写入输出流,传到服务端
out.println(line);
/*键盘录入时,按ctrl+c是空,out将空发出去了,写入并不能停止,
那边还在等,所以要做一次判断,如果是空,就结束*/

//读取服务端传过来的信息
String info = bufIn.readLine();
//如果服务端返回的信息包含标记,就跳出循环
//先打印完服务端返回来的信息,在判断是不是有欢迎
so.p("info: "+info);
if(info.contains("欢迎"))
break ;
}


bufr.close();
s.close();
}
}
class UserThread implements Runnable
{
private Socket s ;
UserThread(Socket s)
{
this.s = s ;
}
public void run()
{
// 校验
String ip = s.getInetAddress().getHostAddress();
so.p(ip+"......connected");
try
{

//服务端只校验3次
for(int x= 0 ; x<3; x++)
{
//获取客户端发来的用户名
BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
String name = bufIn.readLine();
//读一下
BufferedReader bufr = new BufferedReader(new FileReader("c:\\数据源.txt"));
PrintWriter out = new PrintWriter (s.getOutputStream(),true);
String line = null ;

boolean flag = false ;
while((line=bufr.readLine())!=null)//操作文件可以判断读到结尾
{
if(line.equals(name))
{
flag = true ;
break ;
}
}

if(flag)
{
so.p(name+",已登录");
out.println(name+",欢迎光临");
break ;
}
else
{
so.p(name+",尝试登录");
out.println(name+",用户名不存在");//这里不能写成print,否则会报空指针异常
so.p(name+",用户名不存在");
}
}
s.close();
}
catch (Exception e)
{
throw new RuntimeException(ip+"校验失败");
}
}
}


class  LoginServer
{
public static void main(String[] args) throws Exception
{
ServerSocket ss = new ServerSocket(10050);
while(true)
{
Socket s = ss.accept();
new Thread(new UserThread(s)).start();
}
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值