您的位置:首页 > 理论基础 > 计算机网络

黑马程序员-网络编程之TCP传输小总结

2013-12-11 18:29 661 查看
----------------------
ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------

TCP传输:

Socket和ServerSocket分别表示TCP传输的两个端点,客户端和服务端,不同于UDP的DatagramSocket类既可以表示接收端也可以表示发送端。

客户端:
//创建客户端的Socket服务,指定目的主机和端口
//这一步一旦建立成功,就客户端和服务端之间就形成了字节流
Socket s=new Socket("127.0.0.1",10004);

//为了发送数据,应该获取Socket中的输出流。这个输出流是将字节写入此客户端Socket。一旦写入,就发送给服务器端。
//s.getOutputStream()对象的目的是服务器端中此Socket对象A对应的一个Socket对象A‘。服务器端将A'实例化后
//就通过A'的getInputStream()流的read来获取A的getOutputStream()流write出的数据。
OutputStream out=s.getOutputStream();

out.write("tcp ge men lai le".getBytes());

s.close();

服务器端:

//监理服务端socket服务,并监听一个端口。
ServerSocket ss=new ServerSocket(10004);

//通过accept方法获取链接过来的客户端Socket对象。
//accept方法是一个阻塞式方法,启动后会一直监听等着一个Socket来链接
Socket s=ss.accept();

//得到客户端对象的ip地址
String ip=s.getInetAddress().getHostAddress();
System.out.println(ip+"..connected");

//获取客户端发送过来的数据,那么先在服务器端实例化一个客户端对应的Socket对象,然后通过这
//个对象的getInputStream()
//流来获取客户端write出的数据
//s.getInputStream()流对象的源是客户端此Socket
InputStream in=s.getInputStream();

byte[]buf=new byte[1024];
int len=in.read(buf);
System.out.println(new String(buf,0,len));

s.close();//关闭客户端。服务端一般情况下可以关闭客户端,但是不关闭服务端自己
ss.close();//关闭服务端,可选操作
注意,说白了,其实就是客户端和服务端都有一个Socket对象,这两个对象都有自己的读写流,我写你读,我读你写。

/*演示Tcp传输
* 1 Tcp分客户端和服务端。
* 2 客户端对应的对象是Socket,服务端对应的对象是ServerSocket
*
*
* */

/*
* 需求:给服务端发送一个文本数据。
* 客户端:通过查阅socket对象,发现在该对象建立时,就可以连接指定主机。
* 因为tcp是面向连接的,所以在建立socket服务时就要有服务端存在并连接成功。形成通路后,在该通道形成数据的传输
* 步奏:
* 1,创建Socket服务,并指定要连接的主机和端口。
* 2,
* */
class TCPClient{
public static void main(String []args) throws Exception{
//创建客户端的Socket服务,指定目的主机和端口
//这一步一旦建立成功,就客户端和服务端之间就形成了字节流
Socket s=new Socket("127.0.0.1",10004);

//为了发送数据,应该获取Socket中的输出流。这个输出流是将字节写入此客户端Socket。一旦写入,就发送给服务器端。
//s.getOutputStream()对象的目的是服务器端中此Socket对象A对应的一个Socket对象A‘。服务器端将A'实例化后
//就通过A'的getInputStream()流的read来获取A的getOutputStream()流write出的数据。
OutputStream out=s.getOutputStream();

out.write("tcp ge men lai le".getBytes());

s.close();
}
}

/*
* 需求:定义端点接收数据并打印在控制台上。
*
* 服务端:
* 1,建立服务端的Socket服务,通过ServerSocket()建立,并监听一个端口
* 2,获取链接过来的客户端对象。通过ServerSocket的accept方法。所以这个方是阻塞式的
* 3,客户端如果发过来数据,那么服务端要使用对应的客户端对象,并获取到该客户端对象的读取流来读取发过来的数据并打印
* 在控制台。
* 4,关闭服务端。(可选)
* */

class TCPServer{
public static void main(String[]args) throws Exception{
//监理服务端socket服务,并监听一个端口。
ServerSocket ss=new ServerSocket(10004);

//通过accept方法获取链接过来的客户端Socket对象。
//accept方法是一个阻塞式方法,启动后会一直监听等着一个Socket来链接
Socket s=ss.accept();

//得到客户端对象的ip地址
String ip=s.getInetAddress().getHostAddress();
System.out.println(ip+"..connected");

//获取客户端发送过来的数据,那么先在服务器端实例化一个客户端对应的Socket对象,然后通过这个对象的getInputStream()
//流来获取客户端write出的数据
//s.getInputStream()流对象的源是客户端此Socket
InputStream in=s.getInputStream();

byte[]buf=new byte[1024];
int len=in.read(buf);
System.out.println(new String(buf,0,len));

s.close();//关闭客户端。服务端一般情况下可以关闭客户端,但是不关闭服务端自己
ss.close();//关闭服务端,可选操作
}
}
/*演示tcp传输的客户端和服务端的互访。
* 需求:客户端给服务端发送数据,服务端收到后,给客户端反馈信息。
* */

/*
* 客户端:
* 1,建立socket服务。指定要连接的主机和端口
* 2,获取socket流中的输出流,将数据写到该流中,通过网络发送到服务端
* 3,获取socket流中的输入流,将服务端反馈的数据获取到,并打印
* 4,关闭客户端资源
* */
class TcpClient2{
public static void main(String[]args) throws Exception{
Socket s=new Socket("127.0.0.1",10004);
OutputStream out=s.getOutputStream();
out.write("服务端你好!".getBytes());

//同样道理,客户端的Socket对象的getInputStream流的源是服务端的相应Socket对象,它write后我read
InputStream in=s.getInputStream();

byte[] buf=new byte[1024];
int len=in.read(buf);

System.out.println(new String(buf,0,len));
s.close();
}
}

class TcpServer2{
public static void main(String[]args) throws Exception{
ServerSocket ss=new ServerSocket(10004);

Socket s=ss.accept();

String ip=s.getLocalAddress().getHostAddress();

System.out.println(ip+" ..connected");

InputStream in=s.getInputStream();

byte[] buf=new byte[1024];

int len=in.read(buf);//read方法也是阻塞式的,客户端不来数据我就在这里等数据

System.out.println(ip+"::"+new String(buf,0,len));

OutputStream out=s.getOutputStream();

out.write("哥们收到!你也好!".getBytes() );

ss.close();
}
}


通过服务器端实现对输入字符串大小写互换功能。

/*
* 需求:建立一个文本转换器。
* 客户端给服务端发送文本,服务端会将文本转成大写返回给客户端。
* 而且客户端可以不断的进行文本转换,当客户端输入over时,转换结束。
* */
class TcpClient3{

static BufferedReader br;
static BufferedWriter bf;
static BufferedReader br1;

public static void main(Stri
4000
ng[]args) throws Exception{
Socket s=new Socket("127.0.0.1",10005);
OutputStream out=s.getOutputStream();

br=new BufferedReader(new InputStreamReader(System.in));//读取键盘输入
bf=new BufferedWriter(new OutputStreamWriter(out));//发送到服务端
br1=new BufferedReader(new InputStreamReader(s.getInputStream()));//读取服务端发来的数据

System.out.println("请输入:");

String line=null;
while((line=br.readLine())!=null ){//键盘输入若干字符和一个回车表示一行,readLine()读取了字符舍弃回车符。也就是说line中不包含回车符
if(line.equals("over")) break;
bf.write(line);
bf.newLine();//再写入一个回车符
bf.flush();
System.out.println("服务器说:"+br1.readLine());
}

s.close();
bf.close();
br.close();
br1.close();
}
}

class TcpServer3{
public static void main(String[]args) throws Exception{
ServerSocket ss=new ServerSocket(10005);
Socket s=ss.accept();
String ip=s.getInetAddress().getHostAddress();
System.out.println("ip:"+ip+"...connected");

BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));

String line=null;
while((line=br.readLine())!=null){

System.out.println(line);

char b[]=line.toCharArray();

for(int i=0;i<b.length;i++){
if(b[i]<='z' && b[i]>='a')b[i]-=32;
else if(b[i]<='Z' && b[i]>='A')b[i]+=32;
}

bw.write(new String(b));
bw.newLine();
bw.flush();

}
}
}


向服务器上传文本文件。
class TextClient{
public static void main(String[]args) throws Exception{
Socket s=new Socket("127.0.0.1",10006);

BufferedReader br=new BufferedReader(new FileReader("D:\\workspace\\exam\\src\\com\\itheima\\Test9.java"));

PrintWriter out=new PrintWriter(s.getOutputStream(),true);

String line=null;

while((line=br.readLine())!=null){
out.println(line);
}

s.shutdownOutput();//关闭客户端的输出流。相当于给流中加入一个结束标记-1.

BufferedReader bufin=new BufferedReader(new InputStreamReader(s.getInputStream()));

String line1=bufin.readLine();

System.out.println(line1);

br.close();

s.close();

bufin.close();
}
}

class TextServer{
public static void main(String []args) throws Exception{
ServerSocket ss=new ServerSocket(10006);
Socket s=ss.accept();
String ip=s.getInetAddress().getHostAddress();
System.out.println(ip+" connnected");
BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintWriter out=new PrintWriter(new FileWriter("Server.txt"));
String line=null;
while((line=br.readLine())!=null){
out.println(line);
}
PrintWriter pw=new PrintWriter(s.getOutputStream(),true);
pw.println("恭喜你,上传成功!");
out.close();
s.close();
ss.close();
}
}

并行向服务器上传图片。思想是服务端做成多线程。
/*向服务器上传图片*/

/*
* 客户端:
* 1,服务端点
* 2,读取客户端已有的图片数据
* 3,通过socket输出流发送给服务端
* 4,读取服务端反馈信息
* 5,关闭
* */
class UpClient{
public static void main(String[]args) throws Exception{
if(args.length!=1){
System.out.println("请选择一个图片文件");
return;
}
File file=new File(args[0]);
if(!(file.exists() && file.isFile())){
System.out.println("文件不存在或不是文件");
return;
}

if(!args[0].endsWith(".jpg")){
System.out.println("请选择jpg文件");
return;
}

if(file.length()>1024*1025*5){
System.out.println("请选择小于5m的图片");
return;
}

Socket s=new Socket("127.0.0.1",10007);
BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file));
BufferedOutputStream bos=new BufferedOutputStream(s.getOutputStream());
BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));

byte[] b=new byte[1024];
int len;
while((len=bis.read(b))!=-1){
bos.write(b, 0, len);
bos.flush();
}
s.shutdownOutput();

System.out.println(br.readLine());

s.close();
bis.close();
bos.close();
br.close();
}
}

/*
* 服务端的服务代码都写在线程类中,以实现并发。
* */
class PicThread implements Runnable{
private Socket s;
PicThread(Socket s){
this.s=s;
}
public void run(){
String ip=s.getInetAddress().getHostAddress();
int count=1;
try {
System.out.println(ip+"...connected");
BufferedInputStream bis;

bis = new BufferedInputStream(s.getInputStream());

File file=new File("D:\\"+ip+"("+count+").jpg");//同一客户端发过来的图片名称都定义为它的ip号,以区别其他客户端
while(file.exists()){//如果此名称已存在,即已有这个客户端发来图片,那么新传来的图片尾号自动加1,防止同名覆盖
file=new File("D:\\"+ip+"("+(++count)+").jpg");
}

BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(file));
PrintWriter pw=new PrintWriter(s.getOutputStream(),true);

int len;
byte[] b=new byte[1024];
while((len=bis.read(b))!=-1){
bos.write(b, 0, len);
}
pw.println("上传完毕");

s.close();
bis.close();
bos.close();
pw.close();
} catch (Exception e) {
throw new RuntimeException(ip+"...上传失败");
}

}
}

/*
* 服务器原理:
* 将服务代码写入线程run方法,这样每次接收到一个新的请求时就开启一个线程。
* 之后主线程再次accept阻塞等待,再来新请求再次开启一个新线程。
* */
class UpServer{
public static void main(String[]args) throws Exception{
ServerSocket ss=new ServerSocket(10007);
while(true){
Socket s=ss.accept();
new Thread(new PicThread(s)).start();
}
}
}

----------------------
ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: