socket 通讯原理

写道

socket相关知识

1.socket的定义:
所谓socket通常也称作"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求。 以J2SDK-1.6为例,Socket和ServerSocket类库位于java .net包中。ServerSocket用于服务器端,Socket是建立网络连接时使用的。在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话。对于一个网络连接来说,套接字是平等的,并没有差别,不因为在服务器端或在客户端而产生不同级别。不管是Socket还是ServerSocket它们的工作都是通过SocketImpl类及其子类完成的。

2.Socket API (比较重量级的api)
  accept()方法用于产生"阻塞",直到接受到一个连接,并且返回一个客户端的Socket对象实例。"阻塞"是一个术语,它使程序运行暂时"停留"在这个地方,直到一个会话产生,然后程序继续;通常"阻塞"是由循环产生的。
getInputStream方法获得网络连接输入,同时返回一个InputStream对象实例。getOutputStream方法连接的另一端将得到输入,同时返回一个OutputStream对象实例。 注意:其中getInputStream和getOutputStream方法均可能会产生一个IOException,它必须被捕获,因为它们返回的流对象,通常都会被另一个流对象使用。
 
写道
常用的Socket类型

有两种:流式Socket(SOCK_STREAM)和数据报式Socket(SOCK_DGRAM)。流式是一种面向连接的Socket,针对于面向连接的TCP服务应用;数据报式Socket是一种无连接的Socket,对应于无连接的UDP服务应用。 Socket建立为了建立Socket,程序可以调用Socket函数,该函数返回一个类似于文件描述符的句柄。socket函数原型为:int socket(int domain, int type, int protocol);domain指明所使用的协议族,通常为AF_INET,表示互联网协议族(TCP/IP协议族);type参数指定socket的类型:SOCK_STREAM 或SOCK_DGRAM,Socket接口还定义了原始Socket(SOCK_RAW),允许程序使用低层协议;protocol通常赋值0。Socket()调用返回一个整型socket描述符,你可以在后面的调用使用它。 Socket描述符是一个指向内部数据结构的指针,它指向描述符表入口。调用Socket函数时,socket执行体将建立一个Socket,实际上"建立一个Socket"意味着为一个Socket数据结构分配存储空间。 Socket执行体为你管理描述符表。两个网络程序之间的一个网络连接包括五种信息:通信协议、本地协议地址、本地主机端口、远端主机地址和远端协议端口。Socket数据结构中包含这五种信息。
 
写道
开发原理:
服务器,使用ServerSocket监听指定的端口,端口可以随意指定(由于1024以下的端口通常属于保留端口,在一些操作系统中不可以随意使用,所以建议使用大于1024---65535的端口),等待客户连接请求,客户连接后,会话产生;在完成会话后,关闭连接。

客户端,使用Socket对网络上某一个服务器的某一个端口发出连接请求,一旦连接成功,打开会话;会话完成后,关闭Socket。客户端不需要指定打开的端口,通常临时的、动态的分配一个1024以上的端口。

 

代码如下:

服务器端:

package com.xiawenquan.serversocket.demo;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
 * 发送端:
 * @author xiawenquan
 *
 */
public class FileSenderServerce {

	private static ServerSocket serverSocket = null;
	
	public static void main(String[] args) {
		new FileSenderServerce().startSend("F:\\FunshionMedia\\android手机服务器FtpDemo.txt",8080);
	}
	
	private void startSend(String filePath,int port) {
		// TODO Auto-generated method stub
		DataOutputStream outputStream = null;
		DataInputStream inputStream = null;
		Socket socket = null;
		try {
			
			File file = new File(filePath);
			serverSocket = new ServerSocket(port);
			System.out.println("连接通道已经建立");
			while(true){//可以连接多个客户端
				socket = serverSocket.accept();
				System.out.println("正式建立连接");
				
				if(socket != null){
					outputStream = new DataOutputStream(socket.getOutputStream());
					// 将文件名及长度传给客户端。这里要真正适用所有平台,例如中文名的处理,还需要加工,
					// 具体可以参见Think In Java 4th里有现成的代码。
					outputStream.writeUTF(file.getName());
					System.out.println("发送文件名称 == " + file.getName());
					outputStream.writeLong((long) file.length());
					System.out.println("发送文件大小 == " + file.length());
					outputStream.flush();//发送
					
					
					//从本地读取要上传的文件
					inputStream = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
					int buffSize = 1024;
					byte buff[] = new byte[buffSize];
					while(true){
						if(inputStream != null){
							int zise = inputStream.read(buff);
							if(zise == -1){
								break;
							}
							
							outputStream.write(buff, 0, zise);//把读取的数据写到输出流中
						}
					}
					outputStream.flush();//把输出流中的数据刷新出去
					System.out.println("上传完成");
				}
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			
		}finally {// 关闭所有连接
			try {
				if(outputStream != null){
					outputStream.close();
				}
				
				if(inputStream != null){
					inputStream.close();
				}
				
				if(socket != null){
					socket.close();
				}
				
				if(serverSocket != null){
					serverSocket.close();
				}
				
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}
 

接收端:

 

package com.xiawenquan.serversocket.demo;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.net.Socket;

public class FlieAcceptClient {

	
	public static void main(String[] args) {
		//192.168.0.5本机的ip
		new FlieAcceptClient().getFile("F:\\FunshionMedia\\aa\\", "192.168.0.5", 8080);
	}
	
	
	private void getFile(String savePath, String ip, int port){
		DataInputStream inputStream = null;
		DataOutputStream outputStream = null;
		Socket socket = null;
		try {
			
			socket = new Socket(ip, port);
			inputStream = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
			
			int sizeBuff = 1024;
			byte buff[] = new byte[sizeBuff];
			int passedlen = 0;
			
			// 获取文件名称
			
			savePath  += inputStream.readUTF();
			File file = new File(savePath);
			if(file.exists()){
				System.out.println("文件已经存在");
				file.delete();
			}
			//在本地创建一个文件
			outputStream = new DataOutputStream(new BufferedOutputStream(new BufferedOutputStream(new FileOutputStream(file))));
			// 获取文件长度
			long len = inputStream.readLong();
			System.out.println("文件的长度为:" + len + "  KB");
			System.out.println("开始接收文件!");
			
			int readZise = -1;
			// 获取文件
 			while(true){
 				if(inputStream != null){
 					readZise = inputStream.read(buff);
 					if(readZise == -1){
 						break;
 					}
 					passedlen += readZise;
 					System.out.println("文件接收了" + (passedlen * 100 / len) + "%");
 					outputStream.write(buff, 0, readZise);
 					outputStream.flush();
 					
 					if(passedlen == len){
 						break;//当读到的字节大小和文件大小一样就说明已经读完了
 					}
 				}
 				
 			}
 			
 			System.out.println("接收完成,文件存为" + savePath);
 			outputStream.close();
 			
		} catch (Exception e) {
			e.printStackTrace();
			return;
		}finally{
			try {
				if(inputStream != null){
					inputStream.close();
				}
				
				if(outputStream != null){
					outputStream.close();
				}
				
				if(socket != null){
					socket.close();
				}
				
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
}
 

工程如下:

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值