通过socket编程从服务器(桌面)客户端(安卓)发送PNG图像文件 [英] sending png image file from server (desktop) to client (android) via socket programming
问题描述
我已经创建其中Android应用程序作为客户端和服务器驻留在桌面上的Android应用程序。我使用套接字编程进行通信。我已经成功地转移客户端和服务器之间的消息,但我不知道如何将图像传输。 我需要从服务器发送图像文件给客户端,而不是从客户机到服务器
任何人都可以请帮我解决从服务器发送一个PNG图像客户端?
这是我的code迄今:
客户端
私人INT SERVER_PORT = 9999;
类客户端实现Runnable {
私人客户端的Socket;
私人的PrintWriter出来;
私下扫描仪; @覆盖
公共无效的run(){
尝试{
客户端=新的Socket(localhost的,SERVER_PORT);
Log.d(客户,连接到服务器端口+ SERVER_PORT);
OUT =的新PrintWriter(client.getOutputStream());
在=新扫描仪(client.getInputStream());
串线; 而((行= in.nextLine())!= NULL){
Log.d(客户端,服务器云:+线);
如果(line.equals(你好客户)){
通过out.println(回复);
了out.flush();
}
} }赶上(UnknownHostException异常五){
// TODO自动生成catch块
e.printStackTrace();
}赶上(IOException异常五){
// TODO自动生成catch块
e.printStackTrace();
}
} }
服务器类
类ServerThread实现Runnable {
私人ServerSocket的服务器; @覆盖
公共无效的run(){
尝试{
服务器=新的ServerSocket(SERVER_PORT);
Log.d(服务器,开始在端口的服务器+ SERVER_PORT
+和等待客户端...);
而(真){
Socket套接字= server.accept();
Log.d(服务器,
接受socket连接:
+ socket.getLocalAddress());
新主题(新的ClientHandler的(插座))开始()。
}
}赶上(IOException异常五){
// TODO自动生成catch块
e.printStackTrace();
}
} } 类ClientHandler中实现Runnable { 私人插座ClientSocket的;
私人的PrintWriter出来;
私下扫描仪; 公共ClientHandler中(插座clietSocket){
this.clientSocket = clietSocket;
} @覆盖
公共无效的run(){
尝试{
OUT =的新PrintWriter(clientSocket.getOutputStream());
在=新扫描仪(clientSocket.getInputStream());
串线;
Log.d(ClientHandlerThread,与开始通讯:
+ clientSocket.getLocalAddress());
通过out.println(你好客户);
了out.flush();
而((行= in.nextLine())!= NULL){
Log.d(ClientHandlerThread,客户说:+线);
如果(line.equals(回复)){
的out.print(服务器篇);
了out.flush();
}
}
}赶上(IOException异常五){
// TODO自动生成catch块
e.printStackTrace();
} } }
在这里你有服务器和客户端codeS,从服务器发送/接收(图像)文件到客户端。
客户端保存在外部存储图像,改变,如果你想保存到其他地方。
客户端函数返回接收到的图像的位图,你也可以通过在code注释行避免这种情况。
要使用的功能,使用类似下面的内容:
请注意这两个功能必须从非主UI线程以外的线程调用:
//接收文件
尝试
{
//文件名必须是简单的文件名,不文件分隔符'/'
receiveFile(myClientSocket.getInputStream(),myImage.png);
}
赶上(例外五)
{
e.printStackTrace();
}//发送文件
尝试
{
//文件名必须是一个完全合格的路径
SENDFILE(myServerSocket.getOutputStream(),C:/MyImages/orange.png);
}
赶上(例外五)
{
e.printStackTrace();
}
该接收器功能:(复制并粘贴到客户端)
/ **
*从连接的插座接收图像文件并将其保存到一个文件中。
*所述p为H.;
*它接收到的第一个4字节表示文件的大小
* LT; / P>
*
* @参数是
*从连接插座的InputStream
* @参数文件名
*文件的名称在外部存储保存,不
*文件分割符
* @返回位图重新presenting图像接收o原在出现错误的情况下,
* @throws异常
* @see {@link SENDFILE}为例如何将文件在对方发送。
*
* /
公共位图receiveFile(InputStream为,字符串文件名)抛出异常
{字符串BASEDIR = Environment.getExternalStorageDirectory()getAbsolutePath()。
字符串fileInES = BASEDIR +文件分割符+文件名; //读取包含文件的大小4个字节
字节[] = BSIZE新的字节[4];
INT偏移= 0;
而(偏移< bSize.length)
{
INT面包= is.read(BSIZE,偏移,bSize.length - 偏移);
胶印+ =面包;
}
//将4个字节为int
INT档案大小;
档案大小=(int)的(BSIZE [0]&放大器; 0xff的)下;&下; 24
| (中间体)(BSIZE [1]&安培; 0xff的)下;&下; 16
| (中间体)(BSIZE [2]&放大器; 0xff的)下;&下; 8
| (中间体)(BSIZE [3]&放大器; 0xff的); //缓冲区从套接字读取
// 8K缓冲区足够好
字节[]数据=新的字节[8 * 1024]; INT bToRead;
FOS的FileOutputStream =新的FileOutputStream(fileInES);
BOS的BufferedOutputStream =新的BufferedOutputStream(FOS);
而(档案大小大于0)
{
//确保不读文件大小超过多个字节
如果(档案大小> data.length)bToRead = data.length;
否则bToRead =档案大小;
INT读取动作= is.read(数据,0,bToRead);
如果(读取动作大于0)
{
bos.write(数据,0,读取动作);
档案大小 - =读取动作;
}
}
bos.close(); //接收到的图像转换为位图
//如果你不想返回一个位图注释/删除如下因素线
//并使函数返回void或任何你preFER。
BMP位图= NULL;
FIS的FileInputStream =新的FileInputStream(fileInES);
尝试
{
BMP = BitmapFactory.de codeStream(FIS);
返回BMP;
}
最后
{
fis.close();
}
}
发送器功能:(复制并粘贴到服务器端)
/ **
*将文件发送到连接的插座。
*所述p为H.;
*首先,它在发送4个字节的文件大小则该文件的内容。
* LT; / P>
*所述p为H.;
*注:文件大小限制为32位有符号整数,2GB
* LT; / P>
*
* @参数OS
*连接插座的OutputStream
* @参数文件名
*图像的完整文件的路径发送
* @throws异常
* @see {@link receiveFile}一个例子,如何在对方收到的文件。
*
* /
公共无效SENDFILE(OutputStream的OS,字符串文件名)抛出异常
{
//要发送的文件
myfile文件=新的文件(文件名);
INT FSIZE =(int)的myFile.length();
如果(FSIZE&下; myFile.length())
{
的System.out.println(文件过大');
抛出新IOException异常(文件太大了。);
} //发送文件的大小
字节[] = BSIZE新的字节[4];
BSIZE [0] =(字节)((FSIZE&放大器; 0xff000000)GT;> 24);
BSIZE [1] =(字节)((FSIZE&放大器; 0x00ff0000)GT;> 16);
BSIZE [2] =(字节)((FSIZE&放大器; 0x0000ff00)GT;→8);
BSIZE [3] =(字节)(FSIZE&放大器; 0x000000ff);
包含文件大小// 4字节
os.write(BSIZE,0,4); //在内存的限制情况下,这个设置为false
布尔noMemoryLimitation = TRUE; FIS的FileInputStream =新的FileInputStream(MYFILE);
二BufferedInputStream为=新的BufferedInputStream(FIS);
尝试
{
如果(noMemoryLimitation)
{
//用来发送整个文件中的一个块
字节[] = outBuffer新的字节[FSIZE]
INT面包= bis.read(outBuffer,0,outBuffer.length);
os.write(outBuffer,0,面包);
}
其他
{
//使用在一个小缓冲区发送,块数
INT面包= 0;
字节[] = outBuffer新的字节[8 * 1024];
而((面包= bis.read(outBuffer,0,outBuffer.length))大于0)
{
os.write(outBuffer,0,面包);
}
}
os.flush();
}
最后
{
bis.close();
}
}
I've created an android application in which the Android application acts as the client and server resides on a desktop. I'm using socket programming for communication. I've successfully transferred messages between client and server, but I don't know how to transfer an image. I need to send image file from server to client, not from client to server
Can anyone please help me with the solution for sending a png image from server to client?
This is my code so far:
Client side
private int SERVER_PORT = 9999;
class Client implements Runnable {
private Socket client;
private PrintWriter out;
private Scanner in;
@Override
public void run() {
try {
client = new Socket("localhost", SERVER_PORT);
Log.d("Client", "Connected to server at port " + SERVER_PORT);
out = new PrintWriter(client.getOutputStream());
in = new Scanner(client.getInputStream());
String line;
while ((line = in.nextLine()) != null) {
Log.d("Client", "Server says: " + line);
if (line.equals("Hello client")) {
out.println("Reply");
out.flush();
}
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Server class
class ServerThread implements Runnable {
private ServerSocket server;
@Override
public void run() {
try {
server = new ServerSocket(SERVER_PORT);
Log.d("Server", "Start the server at port " + SERVER_PORT
+ " and waiting for clients...");
while (true) {
Socket socket = server.accept();
Log.d("Server",
"Accept socket connection: "
+ socket.getLocalAddress());
new Thread(new ClientHandler(socket)).start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class ClientHandler implements Runnable {
private Socket clientSocket;
private PrintWriter out;
private Scanner in;
public ClientHandler(Socket clietSocket) {
this.clientSocket = clietSocket;
}
@Override
public void run() {
try {
out = new PrintWriter(clientSocket.getOutputStream());
in = new Scanner(clientSocket.getInputStream());
String line;
Log.d("ClientHandlerThread", "Start communication with : "
+ clientSocket.getLocalAddress());
out.println("Hello client");
out.flush();
while ((line = in.nextLine()) != null) {
Log.d("ClientHandlerThread", "Client says: " + line);
if (line.equals("Reply")){
out.print("Server replies");
out.flush();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Here you have server and client codes that send/receive (image) files from server to client. Client save the image in external storage, change that if you want to save it somewhere else. The client function returns a Bitmap of the received image, you can also avoid this by commenting the lines in the code.
To use the functions, use something similar to the following:
NOTE these two function must be called from a thread other than the main UI thread:
// To receive a file
try
{
// The file name must be simple file name, without file separator '/'
receiveFile(myClientSocket.getInputStream(), "myImage.png");
}
catch (Exception e)
{
e.printStackTrace();
}
// to send a file
try
{
// The file name must be a fully qualified path
sendFile(myServerSocket.getOutputStream(), "C:/MyImages/orange.png");
}
catch (Exception e)
{
e.printStackTrace();
}
The receiver function: (Copy and paste it to the client side)
/**
* Receive an image file from a connected socket and save it to a file.
* <p>
* the first 4 bytes it receives indicates the file's size
* </p>
*
* @param is
* InputStream from the connected socket
* @param fileName
* Name of the file to save in external storage, without
* File.separator
* @return Bitmap representing the image received o null in case of an error
* @throws Exception
* @see {@link sendFile} for an example how to send the file at other side.
*
*/
public Bitmap receiveFile(InputStream is, String fileName) throws Exception
{
String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
String fileInES = baseDir + File.separator + fileName;
// read 4 bytes containing the file size
byte[] bSize = new byte[4];
int offset = 0;
while (offset < bSize.length)
{
int bRead = is.read(bSize, offset, bSize.length - offset);
offset += bRead;
}
// Convert the 4 bytes to an int
int fileSize;
fileSize = (int) (bSize[0] & 0xff) << 24
| (int) (bSize[1] & 0xff) << 16
| (int) (bSize[2] & 0xff) << 8
| (int) (bSize[3] & 0xff);
// buffer to read from the socket
// 8k buffer is good enough
byte[] data = new byte[8 * 1024];
int bToRead;
FileOutputStream fos = new FileOutputStream(fileInES);
BufferedOutputStream bos = new BufferedOutputStream(fos);
while (fileSize > 0)
{
// make sure not to read more bytes than filesize
if (fileSize > data.length) bToRead = data.length;
else bToRead = fileSize;
int bytesRead = is.read(data, 0, bToRead);
if (bytesRead > 0)
{
bos.write(data, 0, bytesRead);
fileSize -= bytesRead;
}
}
bos.close();
// Convert the received image to a Bitmap
// If you do not want to return a bitmap comment/delete the folowing lines
// and make the function to return void or whatever you prefer.
Bitmap bmp = null;
FileInputStream fis = new FileInputStream(fileInES);
try
{
bmp = BitmapFactory.decodeStream(fis);
return bmp;
}
finally
{
fis.close();
}
}
The sender function: (copy and paste it to the server side)
/**
* Send a file to a connected socket.
* <p>
* First it sends file size in 4 bytes then the file's content.
* </p>
* <p>
* Note: File size is limited to a 32bit signed integer, 2GB
* </p>
*
* @param os
* OutputStream of the connected socket
* @param fileName
* The complete file's path of the image to send
* @throws Exception
* @see {@link receiveFile} for an example how to receive file at other side.
*
*/
public void sendFile(OutputStream os, String fileName) throws Exception
{
// File to send
File myFile = new File(fileName);
int fSize = (int) myFile.length();
if (fSize < myFile.length())
{
System.out.println("File is too big'");
throw new IOException("File is too big.");
}
// Send the file's size
byte[] bSize = new byte[4];
bSize[0] = (byte) ((fSize & 0xff000000) >> 24);
bSize[1] = (byte) ((fSize & 0x00ff0000) >> 16);
bSize[2] = (byte) ((fSize & 0x0000ff00) >> 8);
bSize[3] = (byte) (fSize & 0x000000ff);
// 4 bytes containing the file size
os.write(bSize, 0, 4);
// In case of memory limitations set this to false
boolean noMemoryLimitation = true;
FileInputStream fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);
try
{
if (noMemoryLimitation)
{
// Use to send the whole file in one chunk
byte[] outBuffer = new byte[fSize];
int bRead = bis.read(outBuffer, 0, outBuffer.length);
os.write(outBuffer, 0, bRead);
}
else
{
// Use to send in a small buffer, several chunks
int bRead = 0;
byte[] outBuffer = new byte[8 * 1024];
while ((bRead = bis.read(outBuffer, 0, outBuffer.length)) > 0)
{
os.write(outBuffer, 0, bRead);
}
}
os.flush();
}
finally
{
bis.close();
}
}
这篇关于通过socket编程从服务器(桌面)客户端(安卓)发送PNG图像文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!