Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Проблемы с локальными сокетами, подскажите пожалуйста

54K
15 декабря 2009 года
Ulis
3 / / 15.12.2009
Здравствуйте, прошу подсказать по теме сокетов в Unix. Мне нужно сделать несколько лабороторных по сокетам разных типов. В данный момент разбираюсь с локальными. Задача просто до идиотизма, но есть какие-то нюансы, которые я со своим скудным опытом не могу преодалеть. Тестирую на Free BSD. Ниже привожу код, клиента и сервера. Программа выполняет простое отзеркаливание. Сервер ловит сообщение от клиента и отправляет обратно.

Сервер:
Код:
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

#define LBUF 100
#define LEN sizeof(struct sockaddr_un)
char bufer[LBUF];
main ()
{

        struct   sockaddr_un  server, client;
        int n, sock, s_len;
        int  c_len = LEN;

   if ((sock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
   {
 printf("Сервер: невозможно создать сокет\n");  exit(1);
   }

   unlink("/home/ntdomain/8m851_aaa/abc.server");
   bzero(&server, LEN);
   server.sun_family = AF_UNIX;
   strcpy(server.sun_path, "/home/ntdomain/8m851_aaa/abc.server");
   s_len=sizeof(server.sun_family)+strlen(server.sun_path);


   if  (bind(sock, (struct  sockaddr *) &server, sizeof(server)) < 0)
   {
    printf("Сервер: ошибка связывания сокета с адресом\n");
    exit(1);
   }



    for (;;)
    {
  n= recvfrom(sock, bufer, LBUF, 0,(struct sockaddr *)&client,(socklen_t*)c_len);

        if (n < 0) continue;

        if (sendto(sock, bufer,n, 0, (struct sockaddr *)&client,(socklen_t)c_len) !=n)
                {
        printf("Сервер: ошибка передачи\n"); continue;
                }
    }

 printf("Сервер: Окончание работы\n");

     
}


Клиент

Код:
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#define LBUF 100
#define LEN sizeof(struct sockaddr_un)
#define STR_LEN 100
char bufer[LBUF];
main (int argc, char* argv[])
{
        char str[STR_LEN];
        struct   sockaddr_un  server, client;
    int n, sock, s_len, c_len, msglen;

   if     ((sock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
    {
      printf("Клиент: невозможно создать сокет\n");  exit(1);
    }

bzero(&client, LEN);
client.sun_family = AF_UNIX;
strcpy(client.sun_path, "/tmp/clnt.XXX");
mktemp(client.sun_path);

c_len= sizeof(client.sun_family) + strlen(client.sun_path);


    if  (bind(sock, (struct  sockaddr *) &client, c_len) < 0)
    {
    printf("Клиент: ошибка связывания сокета с адресом\n");
    exit(1);
     }

    bzero(&server, LEN);
    server.sun_family = AF_UNIX;
    strcpy(server.sun_path, "/home/ntdomain/8m851_aaa/abc.server");
    s_len=sizeof(server.sun_family)+strlen(server.sun_path);


        char msg* = "Тестовое сообщение\n";

         msglen = strlen(msg);

        // отправка
    if (sendto(sock, msg, msglen,0,(struct sockaddr *)&server,sizeof(server)) != msglen)
        {
        printf("Видимо сокет сервера не готов");
        exit(1);
        }


   // получение
    if((n = recvfrom (sock, bufer, LBUF, 0, NULL, 0)) < 0)
     {
         printf("Клиент: ошибка приема\n");
         exit(1);
     }

        printf(bufer);


        close(sock);
        unlink(client.sun_path);
        exit(0);
        }


Сообщения просто напросто не передаются, клиент вообще не подает признаков жизни. В разных модификациях плучалось добится отправки на сервер, но не обратно. В первую очередь мне нужно добится двунаправленной передаяи с локальными дейтаграмными сокетами. Я не знаю, что я делаю не так. Подскажите пожалуйста правильный вариант.
54K
16 декабря 2009 года
Ulis
3 / / 15.12.2009
Мне тут подсказали, что к строкам подобного вида
 
Код:
sizeof(server.sun_family)+strlen(server.sun_path)

нужно добавить +1, чтобы учесть конечный нуль в строке. Замечание справедливое, но должного результата не принесло.
502
16 декабря 2009 года
Jail
550 / / 30.01.2007
Пример-оболочка программы "Клиент":
Код:
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
#define ADDRESS "mysocket" /* адрес для связи */


void main () {
  char c;
  int i, s, len;
  FILE *fp;

  struct sockaddr_un sa;
  /* получаем свой сокет-дескриптор: */

  if ((s = socket (AF_UNIX, SOCK_STREAM, 0))<0) {
    perror ("client: socket"); exit(1);
  }

  /* создаем адрес, по которому
   будем связываться с сервером: */

  sa.sun_family = AF_UNIX;
  strcpy (sa.sun_path, ADDRESS);

  /* пытаемся связаться с сервером: */
  len = sizeof ( sa.sun_family) + strlen ( sa.sun_path);

  if ( connect ( s, &sa, len) < 0 ) {
    perror ("client: connect"); exit (1);
  }

  /* читаем сообщения сервера */
  fp = fdopen (s, "r");
  c = fgetc (fp);

  /* обрабатываем информацию от сервера
  ...................................
  */

  /* посылаем ответ серверу */
  send (s, "client", 7, 0);

  /* продолжаем диалог с сервером, пока в этом
  есть необходимость.....
  */

  /* завершаем сеанс работы */
  close (s);

  exit (0);
}
Пример-оболочка программы "Сервер":
Код:
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
#define ADDRESS "mysocket" /* адрес для связи */
 

void main () {
  char c;
  int i, d, d1, len, ca_len;
  FILE *fp;

  struct sockaddr_un sa, ca;
  /* получаем свой сокет-дескриптор: */

  if((d = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) {
    perror ("client: socket"); exit (1);
  }


  /* создаем адрес, c которым будут
  связываться клиенты */
  sa.sun_family = AF_UNIX;

  strcpy (sa.sun_path, ADDRESS);
  /* связываем адрес с сокетом;
  уничтожаем файл с именем ADDRESS,
  если он существует, для того, чтобы
  вызов bind завершился успешно */

  unlink (ADDRESS);

  len = sizeof ( sa.sun_family) + strlen (sa.sun_path);

  if ( bind ( d, &sa, len) < 0 ) {
     perror ("server: bind"); exit (1);
  }

 
  /* слушаем запросы на сокет */
  if ( listen ( d, 5) < 0 ) {
  perror ("server: listen"); exit (1);
  }


  /* связываемся с клиентом через неименованный сокет
    с дескриптором d1:*/
  if (( d1 = accept ( d, &ca, &ca_len)) < 0 ) {
    perror ("server: accept"); exit (1);
  }

 
  /* пишем клиенту: */
  send (d1, "server", 7, 0);
  /* читаем запрос клиента */

  fp = fdopen (d1, "r");

  c = fgetc (fp);

  /* ................................ */

  /* обрабатываем запрос клиента, посылаем ответ и т.д.
   ........................... */

  /* завершаем сеанс работы */
  close (d1);

  exit (0);
}
Join...
54K
24 декабря 2009 года
Ulis
3 / / 15.12.2009
Спасибо, уже разобрался.
В общем-то тему можно закрывать.

А вообще проблемы с передчей данных как правило возникают из-за капризов к определению строк. Не на всех системах/компиляторах прокатывают строки, определенные через указатель. Лучше делать фиксированный буфер и не забывать его чистить.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог