UDP/TCP
如何实现通信:
1,找到对方IP
2,数据要发送到对方指定的应用程序上。为了标识这些应用程序,所以给这些网络应用程序都用数字进行标识。为了方便称呼这个数字,叫做端口。逻辑端口。
3,定义通信规则。这个通信规则称为协议。
国际组织定义了通用协议。
网络模型
OSI参考模型
TCP/IP参考模型
网络通讯要素
IP地址
网络中设备的标识
不易记忆,可用主机名
本地回环地址:127.0.0.1 主机名:localhost
端口号
用于标识进程的逻辑地址,不同进程的标识
有效端口:0~65535,其中0-1024系统使用或作为保留端口。
传输协议
通讯的规则
常见协议:TCP,UDP
OSI参考模型 TCP/IP参考模型
应用层 | 应用层 |
表示层 | |
会话层 | |
传输层 | 传输层 |
网络层 | 网络层 |
数据链路层 | 主机至网络层 |
物理层 |
UDP
将数据及源和目的封装到数据包中,不需要建立连接
每个数据包的大小限制在64K内
因无连接,是不可靠协议
不需要建立连接,速度快
TCP
建立连接,形成传输数据的通道//三次握手:你在吗?我在。我知道你在了。
在连接中进行大数据量传输
通过三次握手完成连接,是可靠协议
必须建立连接,效率会稍低
Socket
Socket就是为网络服务提供的一种机制。
通信的两端都有Socket
通信其实就是Socket间的通信。
数据在两个Socket间通过IO传输。
UDP发送端
DatagramSocket
DatagramPacket(数据报包)
通过udp传输方式,将一段文字数据发送出去。
思路:
1.建立udpsocket服务。
2.提供数据,并将数据封装到数据包中
3.通过socket服务的发送功能,将数据包发送出去。
4.关闭资源。
定义一个应用程序,用于接收UDP协议传输的数据并处理。
1.定义udpsocket服务。接收端通常会监听一个端口,其实就是给这个接收网络应用程序定义数字标识。方便于明确哪些数据过来,该程序可以处理。
2.定义一个数据包,因为要存储接收到的字节数据。因为数据包对象有更多的功能提取字节数据中的不同数据信息。
3.通过socket服务的receive方法将收到的数据存入已定义好的数据包中。
4.通过数据包对象的特有功能。将这些不同的数据取出,打印在控制台上。
5.关闭资源
TCP传输
Socket和ServerSocket
建立客户端和服务器端
建立连接后,通过Socket中的IO流进行数据的传输。
关闭Socket
同样,客户端与服务器端是两个独立的应用程序。
代码:
package TCPandUDP;
import java.net.*;
publicclassUdpDemo {
publicstaticvoid main(String[] args) throws Exception
{
Threadt1=newThread(newUdpReceive());
Threadt2=newThread(newUdpSend());
t1.start();
t2.start();
}
}
class UdpSend extends Thread
{
publicvoid run()
{
synchronized (UdpSend.class) {
try {
DatagramSocketds = newDatagramSocket();//可以指定一个端口
byte[] buf = "UDP send".getBytes();
DatagramPacketdp = newDatagramPacket(buf, buf.length,
InetAddress.getByName("192.168.1.101"),8000);
ds.send(dp);
System.out.println("udp send");
ds.close();
}catch(Exception e) {
e.printStackTrace();
}
}
}
}
class UdpReceive extends Thread
{
publicvoid run()
{
synchronized (UdpDemo.class) {
try {
DatagramSocketds = newDatagramSocket(8000);//监听端口
byte[] buf = newbyte[1024];
DatagramPacketdp = newDatagramPacket(buf, buf.length);
ds.receive(dp);
Stringip = dp.getAddress().getHostAddress();
Stringdata = newString(dp.getData(), 0, dp.getLength());
int port = dp.getPort();
System.out.println(ip + "::" + data + "::" + port);
System.out.println("udp rece");
ds.close();
}catch(Exception e) {
e.printStackTrace();
}
}
}
}
TCP传输
1,tcp分客户端和服务端
2,客户端对应的对象是Socket
服务端对应的对象是ServerSocket。
客户端
通过查阅socket对象,发现在该对象建立时,就可以去连接指定主机。
因为tcp是面向连接的。所以在建立socket服务时。
就要有服务端存在,并连接成功。形成通路后,在该通道进行数据的传输。
1,创建Socket服务,并指定要连接的主机和端口。
2,获取Socket流中的输出流对象,向流中写入数据,通过网络发送给服务端。
3,关闭客户端资源
服务端:
1,建立服务端的socket服务,ServerSocket();
并监听一个端口。
2,获取连接过来的客户端对象。
通过ServerSocket的accept方法。没有机会就等,所以这个方法是阻塞式的。
3,客户端如果发过来数据,那么服务端要使用对应的客户端对象,并获取到该客户端对象的读取流来读取发过来的数据,并打印在控制台。
4,关闭服务器(可选)
代码:
package TCPandUDP;
import java.io.*;
import java.net.*;
publicclassTcpDemo {
publicstaticvoid main(String[] args) throws Exception
{
Threadt1=newThread(newTcpServer());
Threadt2=newThread(newTcpClient());
t1.start();
t2.start();
}
}
class TcpClient extends Thread
{
publicvoid run()
{
try {
Sockets = newSocket("192.168.1.101", 8002);
OutputStreamout = s.getOutputStream();
out.write("Tcp Run".getBytes());
System.out.println("Client run");
s.close();
}catch(Exception e) {
e.printStackTrace();
}
}
}
class TcpServer extends Thread {
publicvoid run()
{
try {
ServerSocketss = newServerSocket(8002);
Sockets = ss.accept();
Stringip = s.getInetAddress().getHostAddress();
System.out.println(ip + "...connected");
InputStreamin = s.getInputStream();
byte[] buf = newbyte[1024];
int len = in.read(buf);
System.out.println(new String(buf, 0, len));
s.close();
ss.close();
}catch(Exception e) {
e.printStackTrace();
}
}
}
多线程上传图片 TCP
import java.io.*;
import java.net.*;
class piclient
{
publicstaticvoid main(String[] args) throws Exception
{
if(args.length!=1)
{
System.out.println("请传入一张图片!");
return;
}
Filefile=new File(args[0]);
if(!(file.exists()&&file.isFile()))
{
System.out.println("文件有问题或不存在!");
return;
}
if(!file.getName().endsWith(".jpg"))
{
System.out.println("请输入jpg格式文件!");
return;
}
if(file.length()>1024*1024*5)
{
System.out.println("文件太大,请重新选择");
return;
}
Socket s=new Socket("192.168.1.100",10008);
FileInputStream fis=new FileInputStream(file);
byte[] buf =newbyte[1024];
OutputStream out=s.getOutputStream();
int len=0;
while((len=fis.read(buf))!=-1)
{
out.write(buf,0,len);
}
s.shutdownOutput();//定义结束标记
InputStream in=s.getInputStream();
byte[] bufin=newbyte[1024];
int num=in.read(bufin);
System.out.println(new String(bufin,0,num));
fis.close();
s.close();
}
}
class PicThreads implements Runnable
{
private Socket s;
public PicThreads(Socket s)
{
this.s=s;
}
publicvoid run()
{
int count=1;
String ip=s.getInetAddress().getHostAddress();
try
{
System.out.println(ip+"......connected");
InputStream in=s.getInputStream();
File file=new File(ip+"("+(count)+").jpg");//count要加括号,否则下面代码会判断file不存在,不能newFile,server线程结束。
while(file.exists())
file=new File(ip+"("+(count++)+").jpg");
FileOutputStream fos=new FileOutputStream(file);
byte [] buf=newbyte[1024];
int len=0;
while((len=in.read(buf))!=-1)
{
fos.write(buf,0,len);
}
OutputStream out=s.getOutputStream();
out.write("上传成功".getBytes());
fos.close();
s.close();
}
catch(Exception e)
{
thrownew RuntimeException("上传失败!");
}
}
}
class piserver
{
publicstaticvoid main(String[] args) throws Exception
{
ServerSocket ss=new ServerSocket(10008);
while(true)
{
Socket s=ss.accept();
new Thread(new PicThreads(s)).start();
}
}
}
正则表达式:符合一定规则的表达式。
作用:用于专门操作字符串。
特点:用于一些特定的符号来表示一些代码操作,这样可以简化书写。
所以学习正则表达式,就是在学习一些特殊符号的使用。
好处:可以简化对字符串的复杂操作。
弊端:符号定义越多,正则越长,阅读性越差。
具体操作功能:API的pattern类
1.匹配:String matches 方法,用规则匹配整个字符串,只要有一个不符合规则,就匹配结束,返回false。
Stringstr=”ab”;
Stringreg=”[bcd][a-z]”;//第一位是bcd其中一个,第二位a-z中任意一个。
Booleanb=str.matches(reg);
Stringstr=”a124235465”;
Stringreg=”[a-z]\\d*”;//\d*数字零次或多次
2.切割:String split();
“.”点表示任意字符 “\.”:按任意字符切 \\. 按 . 切
代码:splitDemo("erkktyuuuidsfddddop","(.)\\1+")//按叠词完成切割
\\按照叠词完成切割,为了可以让规则的结果被重用,可以将规则封装成一个组,组的出现都有编号。从1开始,想要使用已有的组可以通过\n(n就是组的编号)的形式来获取。
3.替换:String str.replaeAll(reg,newstr);
Stringstr1=”fdkkdlldfpppp”;//将叠词替换成单个的词
replaceAllDemo(str1,”(.)\\1+”,”$1”);$代表前面的组,n代表第几个组
方法replaceAllDemo(Stringstr,String reg,String,newStr)
4.获取:将字符串中符合规则的字串取出。
操作步骤:1.将正则表达式封装成对象。
2.让正则表达式和要操作的字符串相关联。
3.关联后,获取正则匹配引擎。
4.通过引擎对符合规则的字串进行操作,比如取出。
代码:
package Regex;
import java.util.regex.*;
publicclassRegexDemo {
publicstaticvoid main(String[] args)
{
getDemo();
}
publicstaticvoid getDemo()
{
Stringstr="mian tian jiu yao fang jia le,da jia";
Stringreg="\\b[a-z]{3}\\b";// \b单词边界
//将规则封装成对象
Patternp=Pattern.compile(reg);
//让正则对象和要作用的字符串相关联,获取匹配器对象。
Matcherm=p.matcher(str);
//System.out.println(m.matches());//其实String类中的matches方法,用的就是Pattern和Matcher对象来完成的。
//只不过被String的方法封装后,用起来较为简单,但是功能却单一。
// booleanb=m.find();//将规则作用到字符串上,并进行符合规则的子串查找
// System.out.println(b);
// System.out.println(m.group());//用于获取匹配后结果
while(m.find())
{
System.out.println(m.group());
System.out.println(m.start()+"..."+m.end());//获取字符串的角标,包含头,不包含尾
}
}
}
编程,获取一个文件中包含的邮箱地址:
classRegDemo
{
public static void main(String[] args)throwsException
{
BufferedReader bufr=
new BufferedReader(newFileReader("D:\\aa.html"));
String line=null;
String matchReg=("[a-zA-Z0-9_]{6,16}@[a-zA-Z0-9]+(\\.[a-zA-Z]+){1,3}");
Pattern p=Pattern.compile(matchReg);
while((line=bufr.readLine())!=null)
{
Matcher m=p.matcher(line);
while(m.find())
{
System.out.println(m.group());
}
}
}
}
------- android培训、 java培训、期待与您交流! ----------