как прочитать файл и передать
Пишу программу сервер.
Она должна сделать снимок экрана, и передать файл через сокет.
код следующий:
Код:
#include <vcl.h>
#pragma hdrstop
#include <fstream.h>
#include "Winsock2.h"
#include <jpeg.hpp>
//---------------------------------------------------------------------------
#define PORT 555
#define BUF_SIZE 64
char buf[BUF_SIZE];
int from_len, err, s_new, sock;
struct sockaddr_in from_sin;
struct sockaddr_in sin;
fstream log_file;
int symb_len;
TJPEGImage *l_jpg;
TImage *l_image;
//---------------------------------------------------------------------------
void main(void) {
printf("Start server...\r\n");
// инициализируем процесс библиотеки wsock32.dll, вызвая функцию WSAStartup
// 0х0101 версия библиотеки которую следует использовать
WSADATA WsaData;
err = WSAStartup (0x0101, &WsaData);
if (err == SOCKET_ERROR){
printf ("WSAStartup() failed: %ld \r\n", GetLastError ());
exit;
};
// объявляем сокет
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// создаем сокет и задаем параметры для сокета
memset ((char *)&sin, '\0', sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = INADDR_ANY; //системный вызов привязан к socket'у с локальным адресом
// связываем сокет с переменной
err = bind( sock, (struct sockaddr *)&sin, sizeof(sin));
if (err < 0){
printf("Bind error.\r\n");
exit;
};
printf("\t Address: %d \r\n", INADDR_ANY);
printf("\t Port: %d \r\n", PORT);
// слушаем заданный порт, 3 - кол параллельных подключений
err = listen (sock, 2);
if (err < 0){
printf("Listen error.\r\n");
exit;
};
printf("\t Listen OK. \r\n");
printf("Server worked!\r\n");
while (true){
from_len = sizeof(from_sin);
s_new = accept(sock, (struct sockaddr*)&from_sin, &from_len);
if (s_new < 0){
printf("Accept error.\r\n");
exit;
};
//делаем снимок экрана
HWND l_hwnd = GetDesktopWindow();
HDC l_dc = GetDC(l_hwnd);
l_image = new TImage(NULL);
l_image->Width = Screen->Width;
l_image->Height = Screen->Height;
::BitBlt( l_image->Canvas->Handle,
0, 0, l_image->Width, l_image->Height,
l_dc, 0, 0, SRCCOPY);
l_jpg = new TJPEGImage();
l_jpg->Assign(l_image->Picture->Bitmap);
l_jpg->SaveToFile("test.jpg");
//<------ здесь надо прочитать файл test.jpg и послать в сокет ---------->
char *buff;
send(s_new, buff, sizeof(buff), 0);
shutdown (s_new, 0);
closesocket (s_new);
};// end while
};
#pragma hdrstop
#include <fstream.h>
#include "Winsock2.h"
#include <jpeg.hpp>
//---------------------------------------------------------------------------
#define PORT 555
#define BUF_SIZE 64
char buf[BUF_SIZE];
int from_len, err, s_new, sock;
struct sockaddr_in from_sin;
struct sockaddr_in sin;
fstream log_file;
int symb_len;
TJPEGImage *l_jpg;
TImage *l_image;
//---------------------------------------------------------------------------
void main(void) {
printf("Start server...\r\n");
// инициализируем процесс библиотеки wsock32.dll, вызвая функцию WSAStartup
// 0х0101 версия библиотеки которую следует использовать
WSADATA WsaData;
err = WSAStartup (0x0101, &WsaData);
if (err == SOCKET_ERROR){
printf ("WSAStartup() failed: %ld \r\n", GetLastError ());
exit;
};
// объявляем сокет
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// создаем сокет и задаем параметры для сокета
memset ((char *)&sin, '\0', sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = INADDR_ANY; //системный вызов привязан к socket'у с локальным адресом
// связываем сокет с переменной
err = bind( sock, (struct sockaddr *)&sin, sizeof(sin));
if (err < 0){
printf("Bind error.\r\n");
exit;
};
printf("\t Address: %d \r\n", INADDR_ANY);
printf("\t Port: %d \r\n", PORT);
// слушаем заданный порт, 3 - кол параллельных подключений
err = listen (sock, 2);
if (err < 0){
printf("Listen error.\r\n");
exit;
};
printf("\t Listen OK. \r\n");
printf("Server worked!\r\n");
while (true){
from_len = sizeof(from_sin);
s_new = accept(sock, (struct sockaddr*)&from_sin, &from_len);
if (s_new < 0){
printf("Accept error.\r\n");
exit;
};
//делаем снимок экрана
HWND l_hwnd = GetDesktopWindow();
HDC l_dc = GetDC(l_hwnd);
l_image = new TImage(NULL);
l_image->Width = Screen->Width;
l_image->Height = Screen->Height;
::BitBlt( l_image->Canvas->Handle,
0, 0, l_image->Width, l_image->Height,
l_dc, 0, 0, SRCCOPY);
l_jpg = new TJPEGImage();
l_jpg->Assign(l_image->Picture->Bitmap);
l_jpg->SaveToFile("test.jpg");
//<------ здесь надо прочитать файл test.jpg и послать в сокет ---------->
char *buff;
send(s_new, buff, sizeof(buff), 0);
shutdown (s_new, 0);
closesocket (s_new);
};// end while
};
Как прочитать файл test.jpg в двоичном режиме и послать в сокет?
Для него будет так:
Код:
IdTCPClient->Host="127.0.0.1";
IdTCPClient->Port=1234;
try
{
IdTCPClient->Connect();
} catch(...)
{
//Ошибка конекта
};
TMemoryStream *Str = new TMemoryStream();
Str->LoadFromFile("test.jpg");
Str->Position=0;
IdTCPClient->WriteStream(Str,false,Str->Size);
IdTCPClient->Disconnect(); //Если надо.
delete Str;
IdTCPClient->Port=1234;
try
{
IdTCPClient->Connect();
} catch(...)
{
//Ошибка конекта
};
TMemoryStream *Str = new TMemoryStream();
Str->LoadFromFile("test.jpg");
Str->Position=0;
IdTCPClient->WriteStream(Str,false,Str->Size);
IdTCPClient->Disconnect(); //Если надо.
delete Str;
Кстате, если будешь что-то подобное использовать - не пиши в файл, сразу сохраняй в Str:
l_jpg->SaveToStream(Str);
Str->Position=0;
Тогда не будет нужды этот файл читать - все и так в памяти.
P.S. Честно признаюсь, что не приходилось использовать эти компаненты для консольных прог. А ГУИ и сервис писал.
Цитата:
Если пишешь на 6-ом билдере и использование чистого API не вопрос идеологии, то проще всего юзать Indy-компанент TIdTCPClient.
Спасибо за ответ, да билдер шестой, но как раз идеология разрешает только API.
Компонент возьму на вооружение.
Я поступил так, читаю файл по блокам 1024 и посылаю в сокет.
Код такой:
Код:
// получаем файл jpg
l_jpg = new TJPEGImage();
l_jpg->Assign(l_image->Picture->Bitmap);
l_jpg->SaveToFile("tmp.jpg");
char buff[1025];
buff[0]=0;
FILE *df;
df = fopen("tmp.jpg", "rb");
while(!feof(df)) {
memset(buff, 0, 1025);
//читаем из файла
fread(buff, 1024, 1, df);
// посылаем в сокет
//send(s_new, buff, strlen(buff), 0);
send(s_new, buff, 1024, 0);
};
l_jpg = new TJPEGImage();
l_jpg->Assign(l_image->Picture->Bitmap);
l_jpg->SaveToFile("tmp.jpg");
char buff[1025];
buff[0]=0;
FILE *df;
df = fopen("tmp.jpg", "rb");
while(!feof(df)) {
memset(buff, 0, 1025);
//читаем из файла
fread(buff, 1024, 1, df);
// посылаем в сокет
//send(s_new, buff, strlen(buff), 0);
send(s_new, buff, 1024, 0);
};
Работает.
Цитата:
Кстате, если будешь что-то подобное использовать - не пиши в файл, сразу сохраняй в Str:
l_jpg->SaveToStream(Str);
Str->Position=0;
Тогда не будет нужды этот файл читать - все и так в памяти.
Догадывался, об этом, но как сделать с потоком не ведаю.
Пробовал сделать так:
Код:
TStream *str;
l_jpg->SaveToStream(str);
str->Position=0;
char buff[1025];
buff[0]=0;
int n;
while( (n=str->Read(buff, 1024))==NULL) {
memset(buff, 0, 1025);
send(s_new, buff, 1024, 0);
};
l_jpg->SaveToStream(str);
str->Position=0;
char buff[1025];
buff[0]=0;
int n;
while( (n=str->Read(buff, 1024))==NULL) {
memset(buff, 0, 1025);
send(s_new, buff, 1024, 0);
};
Прога вылетает.
Как быть с потоком?
Цитата:
Originally posted by SN_ok
Спасибо за ответ, да билдер шестой, но как раз идеология разрешает только API.
Компонент возьму на вооружение.
Я поступил так, читаю файл по блокам 1024 и посылаю в сокет.
Код такой:
Работает.
Догадывался, об этом, но как сделать с потоком не ведаю.
Пробовал сделать так:
Прога вылетает.
Как быть с потоком?
Спасибо за ответ, да билдер шестой, но как раз идеология разрешает только API.
Компонент возьму на вооружение.
Я поступил так, читаю файл по блокам 1024 и посылаю в сокет.
Код такой:
Код:
// получаем файл jpg
l_jpg = new TJPEGImage();
l_jpg->Assign(l_image->Picture->Bitmap);
l_jpg->SaveToFile("tmp.jpg");
char buff[1025];
buff[0]=0;
FILE *df;
df = fopen("tmp.jpg", "rb");
while(!feof(df)) {
memset(buff, 0, 1025);
//читаем из файла
fread(buff, 1024, 1, df);
// посылаем в сокет
//send(s_new, buff, strlen(buff), 0);
send(s_new, buff, 1024, 0);
};
l_jpg = new TJPEGImage();
l_jpg->Assign(l_image->Picture->Bitmap);
l_jpg->SaveToFile("tmp.jpg");
char buff[1025];
buff[0]=0;
FILE *df;
df = fopen("tmp.jpg", "rb");
while(!feof(df)) {
memset(buff, 0, 1025);
//читаем из файла
fread(buff, 1024, 1, df);
// посылаем в сокет
//send(s_new, buff, strlen(buff), 0);
send(s_new, buff, 1024, 0);
};
Работает.
Догадывался, об этом, но как сделать с потоком не ведаю.
Пробовал сделать так:
Код:
TStream *str;
l_jpg->SaveToStream(str);
str->Position=0;
char buff[1025];
buff[0]=0;
int n;
while( (n=str->Read(buff, 1024))==NULL) {
memset(buff, 0, 1025);
send(s_new, buff, 1024, 0);
};
l_jpg->SaveToStream(str);
str->Position=0;
char buff[1025];
buff[0]=0;
int n;
while( (n=str->Read(buff, 1024))==NULL) {
memset(buff, 0, 1025);
send(s_new, buff, 1024, 0);
};
Прога вылетает.
Как быть с потоком?
Что значит "вылетает" - судя по всему - у тебя str не инициализирован.
Цитата:
судя по всему - у тебя str не инициализирован
Действительно ерунда там.
Подкорректировал, работоспособная программа получилась:
Код:
// получаем jpg
l_jpg = new TJPEGImage();
l_jpg->Assign(l_image->Picture->Bitmap);
TMemoryStream *str = new TMemoryStream();
l_jpg->SaveToStream(str);
str->Position=0;
int sn = str->Size;
char buff[1025];
buff[0]=0;
do {
memset(buff, 0, 1025);
str->Read(buff, 1024);
send(s_new, buff, 1024, 0);
}while( str->Position<sn );
l_jpg = new TJPEGImage();
l_jpg->Assign(l_image->Picture->Bitmap);
TMemoryStream *str = new TMemoryStream();
l_jpg->SaveToStream(str);
str->Position=0;
int sn = str->Size;
char buff[1025];
buff[0]=0;
do {
memset(buff, 0, 1025);
str->Read(buff, 1024);
send(s_new, buff, 1024, 0);
}while( str->Position<sn );
Спасибо участникам обсуждения.