Сокеты (Пишу простую сетевую программу клиент неможет отправить пакет.)

Модератор: Модераторы разделов

Аватара пользователя
netelis
Сообщения: 95
ОС: Debian Wheezy i686

Сокеты

Сообщение netelis »

Вот есть сервер

Код:

#include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <time.h> #include <stdlib.h> #include <arpa/inet.h> #include <string.h> #include <pthread.h> #include <signal.h> #include <ctype.h> static char fbuf[100]; void sigalrm1(int num) { }; int s, c; socklen_t sz; struct sockaddr_in ssa, csa; struct sockaddr *sp, *cp; struct hostent *rhost; char *host; time_t itime; int read_sock(char *buf,int sock) { int n=0; if(buf!=(char)NULL){ alarm(10); n=recv(sock,buf,100,0); }; return n; }; int write_sock(int sock,char *buf) { int n=0; if(buf!=NULL){ alarm(10); n=send(sock,buf,100,0); }; return n; }; void *pthr1(void *a1); int ffd; struct hostent *htn; struct in_addr **adl; static char hnm[25]; static char hna[25]; int main(int argc,char **argv) { signal(SIGALRM,sigalrm1); pthread_attr_t pa1,pa2; pthread_t pt1,pt2; void *arg1; void *arg2; pthread_attr_init(&pa1); pthread_attr_init(&pa2); int pr=pthread_create(&pt1,&pa1,pthr1,NULL); if(pr==0) { printf("Server thread \n"); } else { perror("thread 1"); exit(1); }; sleep(10); for(;;){}; return 0; }; void *pthr1(void *) { sp=(struct sockaddr *)&ssa; cp=(struct sockaddr *)&csa; sz=sizeof(ssa); // Создаём сокет s=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(s == -1){ perror("Невозможно создать сокет"); exit(1); } // Резервируем РїРѕСЂС‚ 13 ssa.sin_family = AF_INET; ssa.sin_port = htons(5000); ssa.sin_addr.s_addr = INADDR_ANY; if(bind(s, sp, sz) == -1){ perror("Невозможно занять РїРѕСЂС‚"); exit(1); } // Переводим сокет РІ режим ожидания соединения if(listen(s, 0) == -1){ perror("Невозможно перейти РІ режим ожидания"); exit(1); } while(1){ if((c = accept(s, cp, &sz)) == -1) { perror("Ошибка РїСЂРё выполнении accept"); exit(1); } rhost=gethostbyaddr((char*)(&csa.sin_addr), sizeof(csa.sin_addr), AF_INET); if(h_errno){ printf("gethostbyaddr error: %d\n", h_errno); host=inet_ntoa(csa.sin_addr); } else { host=rhost->h_name; } printf("$ "); char *tstr=new char[255]; gets(tstr);//считую команду с консоли int i=0; //передаю на клиент считаную команду write_sock(c,tstr); //это неработает (получаем пакет от клиента с выводом команды) read_sock(fbuf,c); printf("%s\n",fbuf); close©; } };

Вот клиент который выполняет команду преданную сервером и направляет вывод в файл который затем считывает и должен отправить серверу но это неработает который должен это отобразить printf.

Код:

#include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <time.h> #include <stdlib.h> #include <arpa/inet.h> #include <string.h> #include <fcntl.h> #include <pthread.h> #define BUFSZ 128 static char fbuf[100]; int read_sock(char *buf,int sock) { int n=0; if(buf!=NULL){ n=recv(sock,buf,100,0); }; return n; }; int write_sock(int sock) { int n=0; n=send(sock,fbuf,100,0); return n; }; int s, sz, i; struct sockaddr_in ssa; struct sockaddr *sp; struct in_addr sip; void *pthr1(void *a1); int ffd; struct hostent *htn; struct in_addr **adl; static char hnm[25]; static char hna[25]; int ac; char **av; int main(int argc,char **argv) { ac=argc; av=argv; pthread_attr_t pa1; pthread_t pt1; void *arg1; pthread_attr_init(&pa1); int pr=pthread_create(&pt1,&pa1,pthr1,NULL); if(pr==0) { printf("Create a thread 1\n"); } else { perror("thread 1"); exit(1); }; for(;;){}; return 0; }; void *pthr1(void *) { sp=(struct sockaddr *)&ssa; sz=sizeof(ssa); if(ac!=2){ // Помощь РїРѕ использованию команды printf("Р˜СЃРїРѕР»СЊР·РѕРІР°РЅРёРµ: %s ip-адрес\n",av[0]); exit(1); } if(inet_aton(av[1], &sip) != 1){ printf("Неправильно задан адрес сервера\n"); exit(1); } while(1) { // Создаём сокет s=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(s == -1){ perror("Невозможно создать сокет"); exit(1); } // Задаём адрес сервера ssa.sin_family = AF_INET; ssa.sin_port = htons(5000); ssa.sin_addr = sip; static char cmbf[100]; // gets(cmbf); // Устанавливаем соединение if(connect(s, sp, sz) == -1){ perror("РќРµ удалось установить соединение"); exit(1); } static char buf[BUFSZ]; //static char fbuf[10000]; for(int j=0;j<=BUFSZ;j++) { buf[j]=(char)0x20; }; // Получаем данные РѕС‚ сервера while((i=read_sock(buf,s)) > 0) write(1, buf, i); i=0; strcat(buf," >> ./f1.txt");// перенаправляет стандартный вывод в файл system(buf);//выполняет команду переданную сервером int fdb=open("./f1.txt",O_RDWR | O_CREAT);//открываю файл с выводом команды if(fdb==-1) { perror("open"); exit(0); } else { read(fdb,fbuf,sizeof(fbuf));//считую в буффер содержимое файла write_sock(s);//это неработает (посылаю серверу ответ с выводом команды) close(fdb); }; } };

При посылке сервером считаной команды клиент принимает и выполняет её нормально, а обратная передача клиентом вывода команды посылает ответ, а сервер ничего непринимает. Может ли клиент и принимать так и отсылать данные или только принимать, а сервер только читать?Или мне нужно чтоб обратно передать данные считаной с файла результат выполнения команды нужно чтоб клиент создал внутри сервер, а сервер создал клиент?
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Сокеты

Сообщение NickLion »

Сразу критика. Код немного странный. Странный сам принцип - т.е. на сервере должен кто-то сидеть и вбивать что нужно исполнить на клиенте? Как быть с одновременнным подключением многих клиентов...

UPD извиняюсь не заметил, сейчас подробнее посмотрю
Спасибо сказали:
Аватара пользователя
netelis
Сообщения: 95
ОС: Debian Wheezy i686

Re: Сокеты

Сообщение netelis »

Если брать более простой пример где есть клиент и сервер, то клиент когда подключается к серверу нормально принимает данные, а когда передает их на сервер сервер непринимает. Проблемма в том чтоб заставить и клиент и сервер как передавать так и принимать данные. До подключения многих клиентов я ещё недошол.
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Сокеты

Сообщение NickLion »

Мда... А вы отлаживать не пробовали?

Код: Выделить всё

while((i=read_sock(buf,s)) > 0)

курим man:recv - когда он 0 возвращает?
Спасибо сказали:
Аватара пользователя
netelis
Сообщения: 95
ОС: Debian Wheezy i686

Re: Сокеты

Сообщение netelis »

Пробовал i возвращает 0 всегда. Я код переписал но ничего неизменилось.0 возвращает когда ничего непрочитал и буффер пустой. man recv я читал.
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Сокеты

Сообщение NickLion »

RETURN VALUE
Upon successful completion, recv() shall return the length of the message in bytes. If no messages are available to be received and the peer has performed an orderly shutdown, recv() shall return 0. Otherwise, -1 shall be returned and errno set to indicate the error.

0 - когда сокет ЗАКРЫВАЕТСЯ! Вот я о чем.
Спасибо сказали:
Аватара пользователя
CycaHuH
Сообщения: 85
ОС: FreeBSD; Archlinux; Calculate

Re: Сокеты

Сообщение CycaHuH »

netelis писал(а):
20.02.2009 21:08

Код:

strcat(buf," >> ./f1.txt");// перенаправляет стандартный вывод в файл system(buf);//выполняет команду переданную сервером int fdb=open("./f1.txt",O_RDWR | O_CREAT);//открываю файл с выводом команды if(fdb==-1) { perror("open"); exit(0); } else { read(fdb,fbuf,sizeof(fbuf));//считую в буффер содержимое файла write_sock(s);//это неработает (посылаю серверу ответ с выводом команды) close(fdb); };

Что-то мне подсказывает, что на сервер всегда будет отправляться результат выполнения первой команды.

А зачем у open() флаг O_CREAT?

Да, и не стоит извращаться с system() & open(), лучше использовать popen()

netelis писал(а):
20.02.2009 21:08
close©;

Зачет.
Спасибо сказали:
Аватара пользователя
netelis
Сообщения: 95
ОС: Debian Wheezy i686

Re: Сокеты

Сообщение netelis »

Немного переделал

Код:

#include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <time.h> #include <stdlib.h> #include <arpa/inet.h> #include <string.h> #include <pthread.h> #include <signal.h> #include <ctype.h> #define BUFSZ 100 void sigalrm1(int num) { }; int s, c; socklen_t sz; struct sockaddr_in ssa, csa; struct sockaddr *sp, *cp; struct hostent *rhost; char *host; time_t itime; int read_sock(char *buf,int sock) { int n=0; if(buf!=(char)NULL){ n=recv(sock,buf,100,0); }; return n; }; int write_sock(int sock,char *buf) { int n=0; if(buf!=NULL){ n=send(sock,buf,100,0); }; return n; }; void sock_connect(int i,char *hnm); pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER; void *pthr1(void *a1); int ffd; struct hostent *htn; struct in_addr **adl; static char hnm[25]; static char hna[25]; int main(int argc,char **argv) { pthread_attr_t pa1,pa2; pthread_t pt1,pt2; void *arg1; void *arg2; pthread_attr_init(&pa1); pthread_attr_init(&pa2); int pr=pthread_create(&pt1,&pa1,pthr1,NULL); if(pr==0) { printf("Server thread \n"); } else { perror("thread 1"); exit(1); }; sleep(10); int s2, sz2, i2; struct sockaddr_in ssa2; struct sockaddr *sp2; struct in_addr sip2; struct hostent *htn2; struct in_addr **adl2; static char hnm2[25]; static char hna2[25]; for(;;){ signal(SIGALRM,sigalrm1); sp2=(struct sockaddr *)&ssa2; sz2=sizeof(ssa2); if(argc!=2){ // Помощь по использованию команды printf("Использование: %s ip-адрес\n",argv[0]); exit(1); } if(inet_aton(argv[1], &sip2) != 1){ printf("Неправильно задан адрес сервера\n"); exit(1); } while(1) { // Создаём сокет s2=socket(AF_INET, SOCK_STREAM, 0); if(s2 == -1){ // perror("Невозможно создать сокет"); } // Задаём адрес сервера ssa2.sin_family = AF_INET; ssa2.sin_port = htons(5001); ssa2.sin_addr = sip2; static char cmbf[100]; // gets(cmbf); // Устанавливаем соединение if(connect(s2, sp2, sz2) == -1){ // perror("Не удалось установить соединение"); } else { static char buf[BUFSZ]; //static char fbuf[10000]; int i2=0; static char fbuf[1000]; // Получаем данные от сервера recv(s2,fbuf,sizeof(fbuf),0); printf("%s\n",fbuf); sleep(15); close(s2); }; } }; return 0; }; void *pthr1(void *) { signal(SIGALRM,sigalrm1); sp=(struct sockaddr *)&ssa; cp=(struct sockaddr *)&csa; sz=sizeof(ssa); // Создаём сокет s=socket(AF_INET, SOCK_STREAM, 0); if(s == -1){ perror("Невозможно создать сокет"); } // Резервируем порт 13 ssa.sin_family = AF_INET; ssa.sin_port = htons(5000); ssa.sin_addr.s_addr = INADDR_ANY; if(bind(s, sp, sz) == -1){ perror("Невозможно занять порт"); exit(1); } // Переводим сокет в режим ожидания соединения if(listen(s, 1) == -1){ perror("Невозможно перейти в режим ожидания"); exit(1); } while(1){ // Принимаем соединение if((c = accept(s, cp, &sz)) == -1) { perror("Ошибка при выполнении accept"); exit(1); } // Выводим время поступления запроса, // адрес и порт отправителя printf("$ "); char *tstr=new char[255]; gets(tstr); int i=0; // Отправляем дату и время клиенту write_sock(c,tstr); // Закрываем соединение close©; } };


Client

Код:

#include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <time.h> #include <stdlib.h> #include <arpa/inet.h> #include <string.h> #include <fcntl.h> #include <pthread.h> #include <signal.h> #define BUFSZ 128 static char fbuf[1000]; void siga(int num) { return; }; int read_sock(char *buf,int sock) { int n=0; if(buf!=NULL){ n=recv(sock,buf,100,0); }; return n; }; int write_sock(int sock) { int n=0; n=send(sock,fbuf,strlen(fbuf),0); return n; }; int s, sz, i; struct sockaddr_in ssa; struct sockaddr *sp; struct in_addr sip; int s2, c2; socklen_t sz2; struct sockaddr_in ssa2, csa2; struct sockaddr *sp2, *cp2; struct hostent *rhost2; char *host2; struct hostent *htn2; struct in_addr **adl2; static char hnm2[25]; static char hna2[25]; void sock_connect(int i,char *hnm); pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER; void *pthr1(void *a1); int ffd; struct hostent *htn; struct in_addr **adl; static char hnm[25]; static char hna[25]; int ac; char **av; int main(int argc,char **argv) { ac=argc; av=argv; pthread_attr_t pa1; pthread_t pt1; void *arg1; pthread_attr_init(&pa1); int pr=pthread_create(&pt1,&pa1,pthr1,NULL); if(pr==0) { printf("Client thread 1\n"); } else { perror("thread 1"); exit(1); }; printf("aaa"); for(;;){ signal(SIGALRM,siga); sp2=(struct sockaddr *)&ssa2; cp2=(struct sockaddr *)&csa2; sz2=sizeof(ssa2); // Создаём сокет s2=socket(AF_INET, SOCK_STREAM, 0); if(s2 == -1){ //perror("Невозможно создать сокет"); } ssa2.sin_family = AF_INET; ssa2.sin_port = htons(5001); ssa2.sin_addr.s_addr = INADDR_ANY; if(bind(s2, sp2, sz2) == -1){ //perror("Невозможно занять порт"); } // Переводим сокет в режим ожидания соединения if(listen(s2, 1) == -1){ // perror("Невозможно перейти в режим ожидания"); } while(1){ // Принимаем соединение if((c2 = accept(s2, cp2, &sz2)) == -1) { //perror("Ошибка при выполнении accept"); } int i=0; send(c2,fbuf,sizeof(fbuf),0); sleep(15); close(c2); } }; return 0; }; void *pthr1(void *) { signal(SIGALRM,siga); sp=(struct sockaddr *)&ssa; sz=sizeof(ssa); if(ac!=2){ // Помощь по использованию команды printf("Использование: %s ip-адрес\n",av[0]); exit(1); } if(inet_aton(av[1], &sip) != 1){ printf("Неправильно задан адрес сервера\n"); exit(1); } while(1) { // Создаём сокет s=socket(AF_INET, SOCK_STREAM, 0); if(s == -1){ perror("Невозможно создать сокет"); exit(1); } // Задаём адрес сервера ssa.sin_family = AF_INET; ssa.sin_port = htons(5000); ssa.sin_addr = sip; static char cmbf[100]; // gets(cmbf); // Устанавливаем соединение if(connect(s, sp, sz) == -1){ perror("Не удалось установить соединение"); exit(1); } static char buf[BUFSZ]; //static char fbuf[10000]; for(int j=0;j<=BUFSZ;j++) { buf[j]=(char)0x20; }; // Получаем данные от сервера while((i=read_sock(buf,s)) > 0) write(1, buf, i); i=0; strcat(buf," > ./f1.txt"); system(buf); int fdb=open("./f1.txt",O_RDWR); if(fdb==-1) { perror("open"); exit(0); } else { read(fdb,fbuf,sizeof(fbuf)); write(1,fbuf,sizeof(fbuf)); close(fdb); }; } };

Работает нормально только на localhost если на одном хосте запускать и клиент и сервер. А если запустить на разных хостах то сервер запустится нормально, а клиент выдаёт сообщение в строке connect perror "No route to host". С чем это может быть связано? Оба хоста пингуются нормально.
Теперь работает нормально. Надо было iptables отключить командой
/etc/rc.d/init.d/iptables stop
Спасибо сказали: