С Новым годом! Форум программистов, компьютерный форум, киберфорум
C/С++ под Linux
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.83/12: Рейтинг темы: голосов - 12, средняя оценка - 4.83
15 / 15 / 2
Регистрация: 20.11.2009
Сообщений: 452

Сокеты отправка сообщений при перессылке файлов

31.05.2011, 15:37. Показов 2315. Ответов 18
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Нужно переслать файлы с клиента на сервер.
сама пересылка идет. Не получается передать имена. Их решил передавать обычным сообщением
По наблюдениям ошибка в клиенте.
у клиента возникает ошибка Program has been terminated receiving signal 13 (Broken pipe)

код сервера

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
 
int main()
{
   int sock, listener;
   struct sockaddr_in addr;
   char buf[2 * 1024];
   FILE *fout;
   int to_read, bytes_read;
   
   if ((listener = socket(AF_INET, SOCK_STREAM, 0)) < 0)
   {
      perror("listener socket");
      exit(1);
   }
   
   addr.sin_family = AF_INET;
   addr.sin_port = htons(2323);
   addr.sin_addr.s_addr = htonl(INADDR_ANY);
   
   if (bind(listener, (struct sockaddr *)&addr, sizeof(addr)) < 0)
   {
      perror("bind");
      exit(2);
   }
   
   listen(listener, 1);
   
   while (1)
   {
      /*Прием сообщений
 
        bytes_read = recvfrom(sock, buf, 1024, 0, NULL, NULL);
        buf[bytes_read] = '\0';
        printf(buf);
*/
      if ((sock = accept(listener, NULL, NULL)) < 0) 
      {
         perror("accept");
         exit(3);
      }
      
      recv(sock, &to_read, sizeof(int), 0);
      printf("%d\n", to_read);
      if (to_read > 0)
      {
         fout = fopen("2.tar.gz", "wb");
         while (to_read > 0)
         {
            printf("Left to read: %d\n", to_read);
            bytes_read = recv(sock, buf, 2 * 1024, 0);
            if (bytes_read <= 0)
               break;
            
            fwrite(buf, bytes_read, sizeof(char), fout);
            to_read -= bytes_read;
         }
         fclose(fout);
      }
      
      close(sock);
   }
   
   return 0;
}
код клиента
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
using namespace std;
 
char buf[2 * 1024];
int main(int argc, char **argv)
{
   char ip[256];
   cout<<"vvedite ip ";
   cin>>ip;
   char name[256];
   cout<<"vvedite ima faila";
   cin>>name;
 int sock;
 struct sockaddr_in addr;
 
 FILE *fin;
 int fsize, bsent, bytes_to_send, total;
 
 sock = socket(AF_INET, SOCK_STREAM, 0);
 if (sock < 0)
 {
    perror("socket");
    exit(1);
 }
 
 addr.sin_family = AF_INET;
 addr.sin_port = htons(2323);
    addr.sin_addr.s_addr = inet_addr (ip);
   /*
     sendto(sock, name, sizeof(name), 0,
            
         (struct sockaddr *)&addr, sizeof(addr));
 
   connect(sock, (struct sockaddr *)&addr, sizeof(addr));
    send(sock, name, sizeof(name), 0);
    close(sock);*/
   //connect i otpravka
   
     if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
 {
    perror("connect");
    exit(2);
 }
 
 if (!(fin = fopen(name, "rb")))
 {
    perror("fopen");
    exit(3);
 }
 
 fseek(fin, 0, SEEK_END);
 fsize = ftell(fin); fseek(fin, 0, SEEK_SET);
 send(sock, &fsize, sizeof(int), 0);
 while (!feof(fin))
 {
    if (!(total = bytes_to_send = fread(buf, sizeof(char), 2 * 1024, fin)))
       break;
     
    while (bytes_to_send > 0)
    {
       bsent = send(sock, buf + (total - bytes_to_send), bytes_to_send, 0);
       printf("Sent: %d\n", bsent);
       if (bsent == -1)
       {
          perror("send");
          exit(4);
       }
       bytes_to_send -= bsent;
    }
 }
 
 fclose(fin);
 printf("File sent\n");
 close(sock);
 
 return 0;
}
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
31.05.2011, 15:37
Ответы с готовыми решениями:

ICQ отправка сообщений через сокеты
Ищу пример логина на сервер ICQ и отправки сообщений через сокеты. Где можно посмотреть реализацию или хотя бы найти описание протокола?...

Отправка и получение сообщений через сокеты
Для начала , вот статья с аналоговым примером. Вот метод для получения сообщений : void Listen(CancellationToken CancellToken){ ...

Сокеты. Отправка сообщений всем клиентам или только одному
Здравствуйте, имеется вот такой сервер на C#: using System; using System.Collections.Generic; using System.Linq; using System.Text;...

18
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
31.05.2011, 16:31
У вас же socket(AF_INET, SOCK_STREAM, 0) соответственно сервер сначала должен сделать accept, а потом уже принимать данные, будет ли это read/recv/recvfrom/recvmsg не важно. Для клиента все тоже самое - сначала connect(), потом отправка.
0
15 / 15 / 2
Регистрация: 20.11.2009
Сообщений: 452
31.05.2011, 17:03  [ТС]
Имя файла передалось. Но срывается сама передача
Код сервера
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
 #include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
 
int main()
{
   int sock, listener;
   struct sockaddr_in addr;
   char buf[2 * 1024];
   FILE *fout;
   int to_read, bytes_read;
   
   if ((listener = socket(AF_INET, SOCK_STREAM, 0)) < 0)
   {
      perror("listener socket");
      exit(1);
   }
   
   addr.sin_family = AF_INET;
   addr.sin_port = htons(2323);
   addr.sin_addr.s_addr = htonl(INADDR_ANY);
   
   if (bind(listener, (struct sockaddr *)&addr, sizeof(addr)) < 0)
   {
      perror("bind");
      exit(2);
   }
   
   listen(listener, 1);
   
   while (1)
   {
      
      if ((sock = accept(listener, NULL, NULL)) < 0) 
      {
         perror("accept");
         exit(3);
      }
 
       /*Прием сообщений
*/
        bytes_read = recvfrom(sock, buf, 1024, 0, NULL, NULL);
        buf[bytes_read] = '\0';
        printf(buf);
 
      recv(sock, &to_read, sizeof(int), 0);
      printf("%d\n", to_read);
      if (to_read > 0)
      {
         fout = fopen(buf, "wb");
         while (to_read > 0)
         {
            printf("Left to read: %d\n", to_read);
            bytes_read = recv(sock, buf, 2 * 1024, 0);
            if (bytes_read <= 0)
               break;
            
            fwrite(buf, bytes_read, sizeof(char), fout);
            to_read -= bytes_read;
         }
         fclose(fout);
      }
      
      close(sock);
   }
   
   return 0;
}


Код клиента
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
using namespace std;
 
char buf[2 * 1024];
int main(int argc, char **argv)
{
    char ip[256];
    cout<<"vvedite ip ";
    cin>>ip;
    char name[256];
    cout<<"vvedite ima faila";
    cin>>name;
  int sock;
  struct sockaddr_in addr;
  
  FILE *fin;
  int fsize, bsent, bytes_to_send, total;
  
  sock = socket(AF_INET, SOCK_STREAM, 0);
  if (sock < 0)
  {
     perror("socket");
     exit(1);
      
  }
 
 
 
 
 
 
 
    addr.sin_family = AF_INET;
  addr.sin_port = htons(2323);
     addr.sin_addr.s_addr = inet_addr (ip);
 
    
      if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
  {
     perror("connect");
     exit(2);
  }
 
      sendto(sock, name, sizeof(name), 0,
             
          (struct sockaddr *)&addr, sizeof(addr));
 
    connect(sock, (struct sockaddr *)&addr, sizeof(addr));
    send(sock, name, sizeof(name), 0);
    close(sock);
    //connect i otpravka
 
    
  if (!(fin = fopen(name, "rb")))
  {
     perror("fopen");
     exit(3);
  }
  
  fseek(fin, 0, SEEK_END);
  fsize = ftell(fin); fseek(fin, 0, SEEK_SET);
  send(sock, &fsize, sizeof(int), 0);
    
  while (!feof(fin))
  {
     if (!(total = bytes_to_send = fread(buf, sizeof(char), 2 * 1024, fin)))
        break;
     
     while (bytes_to_send > 0)
     {
        bsent = send(sock, buf + (total - bytes_to_send), bytes_to_send, 0);
        printf("Sent: %d\n", bsent);
        if (bsent == -1)
        {
           perror("send");
           exit(4);
        }
        bytes_to_send -= bsent;
     }
  }
  
  fclose(fin);
  printf("File sent\n");
  close(sock);
  
  return 0;
}


результат выданный сервером
1.tar.gz1635003953
Left to read: 1635003953
Left to read: 1635003701
0
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
31.05.2011, 17:12
Цитата Сообщение от nikooolay Посмотреть сообщение
buf[bytes_read] = '\0';
что произойдет, если recvfrom() вернет -1 ?

Цитата Сообщение от nikooolay Посмотреть сообщение
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
* {
* * *perror("connect");
* * *exit(2);
* }
sendto(sock, name, sizeof(name), 0,(struct sockaddr *)&addr, sizeof(addr));
connect(sock, (struct sockaddr *)&addr, sizeof(addr));
* * send(sock, name, sizeof(name), 0);
* * close(sock);
* * //connect i otpravka
для чего тут происходит два коннекта и rclose? оО
0
15 / 15 / 2
Регистрация: 20.11.2009
Сообщений: 452
31.05.2011, 17:26  [ТС]
я не совсем понимаю как отделить имя файла от самих данных?
вбить после имени какие-либо символы и их ловить на сервере?
но это будет огород
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
31.05.2011, 17:33
Не, "огород" это то что вы пытаетесь изобразить.
Сделайте например так:
Клиент: FILE размер имя\n
Сервер: OK/ERR\n
Клиент: данные
Сервер: OK/ERR\n

Если же вам очень хочется бинарный протокол то так:
Клиент:uint8_t name_len; off_t file_size; char name[name_len]; data
Сервер: recv()/close()
0
15 / 15 / 2
Регистрация: 20.11.2009
Сообщений: 452
31.05.2011, 17:46  [ТС]
все равно не понял как сервер "поймет" что имя файла ему уже передано если оно меньше 256?
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
31.05.2011, 17:56
В разделе для начинающих вам наверное с удовольствием объяснят как из строки типа "XXX размер имя\n" выдернуть и проверить на валидность размер и имя...
Если же вы про вариант с бинарным протоколом, то длину имени клиент передает первым байтом...
1
15 / 15 / 2
Регистрация: 20.11.2009
Сообщений: 452
31.05.2011, 18:16  [ТС]
выделить я и сам могу.
я про ситуацию когда серверу передались все символы а он продолжает ожидать все до 256.
вот что меня смущает.
Посылка сообщения от клиента со знаком завершения не спасает
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
31.05.2011, 18:25
А зачем он продолжает чего-то ждать то?
Если вы считаете что recv(,, 255, 0) будет ждать пока в буфере появиться именно 255 байт, то это ни так (по крайней мере если не играться с SO_RCVLOWAT).

В конце концов, если не можете иначе, делайте:
recv(, &namelen, 1, 0);
recv(, &filesize, sizeof(off_t), 0);
recv(, name, (size_t)namelen, 0);
Не эффективно да, но вам наверное не важно.
0
15 / 15 / 2
Регистрация: 20.11.2009
Сообщений: 452
31.05.2011, 18:51  [ТС]
Цитата Сообщение от g_u_e_s_t Посмотреть сообщение
А зачем он продолжает чего-то ждать то?
Если вы считаете что recv(,, 255, 0) будет ждать пока в буфере появиться именно 255 байт, то это ни так (по крайней мере если не играться с SO_RCVLOWAT).
тогда почему я получаю следующее
1.tar.gz\n1635003953
Left to read: 1635003953
Left to read: 1635003701

те клиент выслал одни данные, завершил строку начал высылать другие. но сервер не воспринял завершение?
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
31.05.2011, 19:32
Что отправили, то и получили. Почему вы решили, что recv() как-то должен реагировать на "завершил строку" я не знаю. Если вас сильно смущает, что отдельные send() "склеиваются" на сервере - отключите nagle (TCP_NODELAY) на клиенте.
Хотя по-уму отправив имя и размер клиенту не плохо бы подождать какой-то реакции сервера, типа "все ok посылай" / "извиняй имя кривое/нет места на дисках/итп"...

Добавлено через 16 минут
Если вы про TCP_NODELEY, то это заставит клиент отправлять в сеть сразу то, что передает send() не ожидая пока данных накопится на полноценный пакет, например если делать send(,,1,0) будут отправляться пакеты с tcp_payload размер 1 байт. Но то что сервер будет их получать так же по одному не гарантирует.
Перечитал весь топик еще раз:
ну читаете вы 1й килобайт в чем проблема то выудить оттуда байт длины имени, размер и имя файла, а все что сверх того если же таковое имеется считать данными. Для случая если получено меньше чем 1+sizeof(off_t)+1й байт запомнить что пришло и читать дальше?
0
15 / 15 / 2
Регистрация: 20.11.2009
Сообщений: 452
31.05.2011, 19:46  [ТС]
если после получения имени от сервера придет ответ, это будет гарантировать разрыв?
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
31.05.2011, 19:50
Да, если клиент не начнет посылать сам файл пока не прочитает этот ответ. Но сервер по любому должен быть написан так, что б не начудить при _любом_ поведении клиента.
0
15 / 15 / 2
Регистрация: 20.11.2009
Сообщений: 452
31.05.2011, 20:07  [ТС]
Попробовал сделать - теперь уперся в вопрос, как нормально передать ип клиента серверу ? те та же проблема.

клиент продолжает отправлять данные, при этом не ожидая ответ сервера
0
31.05.2011, 20:08

Не по теме:

мне вот любопытно стало... на сколько минимальным можно написать код передачи файлов по сети? :)
на с++, конечно.

0
15 / 15 / 2
Регистрация: 20.11.2009
Сообщений: 452
31.05.2011, 20:15  [ТС]
да в сетях 0, в линуксах 0, но собственно из-за этого я и полез на форум
0
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
31.05.2011, 20:21
nikooolay, это тебе на какой-то зачет?
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
31.05.2011, 20:23
По большому счету тут ни сети ни юниксы не причем.
Представьте, что вам нужно прочитать блок данных определенного формата в памяти или из файла и в качестве инструмента чтения у вас есть функция которая за раз читает не больше (меньше может, а больше ни-ни) чем вы ей указываете байт. И надо постараться уложиться в как можно меньшее к-во вызовов этой функции.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
31.05.2011, 20:23
Помогаю со студенческими работами здесь

Отправка сообщений, файлов и т.д
Всем привет! Недавно решил поработать с сетью и сразу встал вопрос: нашёл на этом форуме код: using System; using System.Net; ...

Отправка сообщений и файлов по сети
Привет. Вообщем делал прогу для отправки сообщений и файлов внутри сети, используя UNOLibs. Если конкретнее, то сделал 1 в 1 как на этом...

Отправка mail сообщений с вложением файлов
Чтобы отправлять сообщения о новом клиенте на почту, использую следующий код: 1) HTML &lt;input type = &quot;text&quot; class =...

Асинхронные сокеты: Как организовать разделение на прием сообщений и прием файлов
Изучив синхронные сокеты, перешел к изучению асинхронных. Столкнулся вот с чем, как, используя асинхронные сокеты, сделать на стороне...

Отправка сообщений при регистрации
Доброго времени суток! Уважаемые форумчане, обращаюсь к вам с вопросом и просьбой помочь мне, начинающему:) Вопрос состоит в следующем, у...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Новые блоги и статьи
Первый деплой
lagorue 16.01.2026
Не спеша развернул своё 1ое приложение в kubernetes. А дальше мне интересно создать 1фронтэнд приложения и 2 бэкэнд приложения развернуть 2 деплоя в кубере получится 2 сервиса и что-бы они. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит токи на L и напряжения на C в установ. режимах до и. . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Изучаю kubernetes
lagorue 13.01.2026
А пригодятся-ли мне знания kubernetes в России?
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru