#android #sockets #file-transfer
#Android #сокеты #передача файлов
Вопрос:
Привет, вот проблема: сервер отправляет изображение клиенту правильно (я думаю). Файл, полученный от клиента, имеет тот же размер, что и файл, присутствующий на сервере phone, поэтому, я думаю, каждый байт был передан, но изображение все равно не видно. Либо сервер, либо клиент являются телефонами Android. Заранее спасибо, надеюсь, вы сможете мне помочь.
Код сервера:
public class FileActivity extends Activity {
private FileInputStream fileInputStream;
private BufferedInputStream bufferedInputStream;
private OutputStream outputStream;
private byte [] mybytearray;
private String tmp = null;
private TextView tv;
private File myFile;
private int l;
private String path;
private EditText editText;
private ServerSocket serverSocket;
private Socket client;
public static String SERVERIP = "10.0.2.15";
private final int SERVERPORT = 8080;
private byte [] imgbyte;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file);
tv = (TextView) findViewById(R.id.textView1);
editText = (EditText) findViewById(R.id.editText1);
SERVERIP = getLocalIpAddress();
Thread sThread = new Thread(new ServerThread());
sThread.start();
}
public void sendListener(View v) {
tmp = editText.getText().toString();
path = "/sdcard/" tmp;
myFile = new File(path);Log.d("SERVER", "WORKS");
l = (int) myFile.length();Log.d("SERVER", "WORKS");
tv.setText(path " " Integer.toString(l));
tmp = Integer.toString(l); Log.d("SERVER", "WORKS");
String test = tmp;
//out.println(tmp);
Log.d("SERVER", "WORKS");
try {
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())), true);
out.println(test);
//out.close();
Log.d("SERVER", "WORKS");
byte[] mybytearray = new byte[1024]; //create a byte array to file
Log.d("SERVER", "WORKS");
fileInputStream = new FileInputStream(myFile);
bufferedInputStream = new BufferedInputStream(fileInputStream);
Log.d("SERVER", "WORKS");
Log.d("SERVER", "WORKS");
try{
outputStream = client.getOutputStream();
} catch(Exception e)
{
Log.d("OUTPUT", "UFFFF");
e.printStackTrace();
}
/* Log.d("SERVER", "ALMOST");
outputStream.write(mybytearray, 0, mybytearray.length); Log.d("SERVER", "DONE");//write file to the output stream byte by byte*/
// outputStream.flush();
// outputStream.close();
Log.d("SERVER", "WORKS");
int count = 0;
int size = 0;
while((count = bufferedInputStream.read(mybytearray, 0 , mybytearray.length)) != -1)
{
// count = bufferedInputStream.read(mybytearray, 0 , mybytearray.length);
size = count;
Log.d("SERVER", "SEND");
try{
outputStream.write(mybytearray, 0, count);
} catch(Exception e) {
e.printStackTrace();
}
Log.d("TEST", Integer.toString(count));
}
Log.d("SERVER", "DONE");
bufferedInputStream.close();
outputStream.close();
client.close();
} catch (Exception e) {
}
}
public class ServerThread implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
try {
serverSocket = new ServerSocket(SERVERPORT);
client = serverSocket.accept();
//outputStream = client.getOutputStream();
Log.d("SERVER", "Connesso");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.d("TEST", "UFFFAAA");
}
}
}
private String getLocalIpAddress() {
String tmp = "";
int i = 0;
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
InetAddress inetAddress = enumIpAddr.nextElement();
if (!inetAddress.isLoopbackAddress())
{
tmp = "IP: " inetAddress.getHostAddress() "n";
}
}
}
} catch (SocketException ex) {
Log.e("ServerActivity", ex.toString());
}
return tmp;
}
@Override
protected void onStop() {
super.onStop();
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Клиентский код:
public class FileActivity extends Activity {
private EditText serverIp, getPort;
private Button connectPhones;
private TextView tv, tvIP;
private Boolean connected = false;
private String serverIpAddress, portStr;
private Socket socket;
private int port, len;
private String filepath;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file);
tvIP = (TextView) findViewById(R.id.IPtv);
tv = (TextView) findViewById(R.id.Portatv);
serverIp = (EditText) findViewById(R.id.server_ip);
connectPhones = (Button) findViewById(R.id.connect_phones);
getPort = (EditText) findViewById(R.id.server_port);
}
public void connectListener(View v)
{
if (!connected) {
serverIpAddress = serverIp.getText().toString();
portStr = getPort.getText().toString();
if (!serverIpAddress.equals("")) {
Thread cThread = new Thread(new ClientThread());
cThread.start();
}
}
}
public class ClientThread implements Runnable
{
@Override
public void run() {
// TODO Auto-generated method stub
port = Integer.parseInt(portStr);
socket = new Socket();
try {
InetAddress serverAddr = InetAddress.getByName(serverIpAddress);
Log.d("ClientActivity", "C: Connessione in corso...");
socket = new Socket(serverAddr, port);
Log.d("ClientActivity", "C: Connesso!");
connected = true;
DataInputStream dis;
try {
dis = new DataInputStream(socket.getInputStream());
int bytes;
byte[] b = new byte[32];
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String l = in.readLine();
//String line = Integer.toString(l);
Log.d("PROVA", l);
try
{
len = Integer.parseInt(l); Log.d("CLIENT", Integer.toString(len));
}
catch (NumberFormatException e)
{
e.printStackTrace();
}
byte[] img = new byte[1082922]; //1082922
FileOutputStream fos = new FileOutputStream("/sdcard/img.jpg");
BufferedOutputStream bos = new BufferedOutputStream(fos);
/*bytes = dis.read(img, 0, img.length);
bos.write(img, 0, img.length);*/
int count = 0;
while ((bytes = dis.read(img)) != -1) {
count = bytes;
Log.d("CLIENT", Integer.toString(count));
Log.d("TEST", Integer.toString(bytes));
//Write to file
bos.write(img, 0, bytes);
}
bos.flush();
bos.close();
Log.d("TCP", "Save to file");
} catch(IOException e){
e.printStackTrace();
}
} catch (Exception e) {
Log.e("ClientActivity", "C: Errore", e);
connected = false;
}
}
}
@Override
protected void onStop() {
super.onStop();
if(connected == true)
{
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Комментарии:
1. В sendListener на стороне сервера — вы читаете первые 1024 байта из BufferedInputStream — никогда не сохраняя их нигде — прежде чем начать фактический цикл чтения / записи.
2. На самом деле вы правы, я этого не заметил! Спасибо! Теперь сервер отправляет все байты! К сожалению, на стороне клиента изображение повреждено, его вообще не видно.. Можете ли вы помочь мне дальше? Заранее большое вам спасибо
Ответ №1:
Вы объединяете буферизованный и небуферизованный ввод-вывод в одних и тех же базовых потоках. Буферизованный считыватель украдет данные из другого потока, заполнив его буфер тем, что доступно. У вас есть потоки ввода и вывода данных: используйте их для всего. Вы можете отправить размер файла с помощью writeInt() / readInt().
Комментарии:
1. Так вот почему полученное изображение повреждено?
2. Конечно, это так. Неверные данные — = повреждение, не так ли?
Ответ №2:
У вас уже есть одно .read()
перед while
циклом. И эти байты вы не делаете write()
, поэтому клиент не получает первые байты файла. O теперь я вижу, что вы их записываете, но не учитываете их размер. В любом случае: плохая конструкция. И для первого чтения вы также должны были использовать переменную count. И записывайте только количество байтов. Лучше полностью удалить первое чтение.
Комментарии:
1. Итак, ошибок нет? И есть идеи, почему сервер не отправляет все байты?
2. Ваш вопрос не имеет смысла. Пожалуйста, внимательно перечитайте то, что я написал.
3. Я не понимаю, что вы имеете в виду. Первый «read ()» предназначен для определения размера файла, а второй «read ()» — для получения самого файла.
4. О, извините, это идея. Хорошая идея сначала отправить размер файла. Но, пожалуйста, объясните, как передается размер. И на стороне сервера вы сначала резервируете 32 байта, после чего вы читаете строку. И вы не извлекаете из него значение. Вместо этого вы используете фиксированный буфер. Я не могу следовать вашему коду. Пожалуйста, объясните.
5. Лучше посмотрите на код вашего сервера, куда отправляется содержимое файла. Вы не определяете там размер файла и не отправляете ни размер файла, ни строку перед отправкой содержимого. Я также видел, что клиент пытается получить целочисленное значение из прочитанной строки.