2012-08-22 32 views
0

我已经实现了一个Android应用程序,该应用程序使用SP相机拍摄照片并通过套接字将其发送到服务器。通过套接字发送的图像流 - 服务器死锁问题

我用下面(JAVA)的代码读取本地存储的图像文件,并在连续的块在插槽发送:

FileInputStream fileInputStream = new FileInputStream("my_image_file_path"); 

int nRead; 
byte[] data = new byte[16384]; 

try { 
    while((nRead = fileInputStream.read(data, 0, data.length)) != -1){ 
     networkOutputStream.write(data, 0, nRead); 
    } 

} catch(IOException e){ 
    e.printStackTrace(); 
} 
fileInputStream.close(); 

而下面的(C/C++),代码读取它并将其存储在服务器上:

char newbuffer[MAX_BUF_SIZE]; 
int checkOperation; 

ofstream outfile("image_file_path".c_str(), ofstream::binary); 

do{ 
    checkOperation = read(clientSocketDescriptor, newbuffer, sizeof(newbuffer)); 

    if(checkOperation < 0){ 

     cout << "Error in recv() function, received bytes = " << checkOperation << endl; 
     exit(1); 
    }else if (checkOperation != 0){ 

     /* 
     * some data was read 
     */ 
     cout << endl << "READ Bytes: " << checkOperation << endl; 
     outfile.write(newbuffer, checkOperation); 

     /* 
     * emptying buffer for new incoming data 
     */ 
     for(int i = 0; i < sizeof(newbuffer); i++){ 
      newbuffer[i] = 0; 
     } 
    } 
}while(checkOperation =! 0); 

outfile.close(); 

Android客户端应用程序似乎正确地写在插座的所有字节,并成功地从while循环退出。

但是,服务器代码卡在while循环的最后一次迭代中,并且无法继续执行。

  • 为什么服务器不能读取EOF
  • 我的代码发送图像或阅读它不正确?

在此先感谢您提供任何帮助,因为我真的被卡住了!

+1

因为你不发送EOF ... – njzk2

回答

3

你没有关闭networkOutputStream,所以C++代码不知道你已经完成了。

要么你需要关闭输出流 - 如果你不需要发送更多数据,显然你只需要关闭输出流;或者你需要在协议中包含一些元数据,以便在开始写之前指明还有多少数据,或者之后包含什么作为“完成”指标。通常我更喜欢长度前缀 - 如果“完成”指标自然出现在数据中,那么它比不必担心转义更简单。

一个中途的房子会反复说“这里有一大块数据长度为X”,然后是“我完成了,没有更多的块”消息(可能是“这是一个数据长度为0的块”例)。这样你事先不需要知道总长度。

+0

我没有关闭'networkOutputStream'因为我需要发送一些其他数据后的图像(一些文本文件与图像的描述)。在你看来,对于我的特殊用例,最好的过程是什么?你需要的时间...... – Matteo

+0

而且,在使用'networkOutputStream.flush()'方法发送图像之后刷新流可以解决问题? – Matteo

+0

@Matteo:不,只是冲洗不会有帮助 - 因为C++代码仍然不知道你已经完成了。如果您需要发送其他信息,我会将每个数据长度作为前缀(即图像的长度前缀,文本信息的另一长度等)。如果在开始编写代码之前找出完整的长度是非常棘手的,那么可以选择分块解决方案。 –