Сървърска п-ма не работи оптимално
програмата е за linux, но е мрежова така че съвместимостта с темата на форума е пълна!
трябва да направя сървър (ще работи на linux) който приема връзки от
клиенти, обработва ги и щом клиента затвори връзката, да е готов да
приеме следващия.
кодът ми е по-долу, но има едим проблем: след затваряне на връзката
повикването на select() ми връща грешка: bad file descriptор! ще
съм ви много благодарен ако ми покажете какво пропускам, къде греша.
кодът е изчестен за форума, инъче има всички нужни проверки за грешки.
/*
Name: LinuxServ.exe
Description: server, reads from file and waits for WinClient to connect
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <winsock.h>
//linux specific headers
/*prototypes*/
int GetDataFromStr(char* str);
int main()
{
//socket variables
fd_set read_fds; // file descriptor list for select()
int sockfd, newfd; // listen on sockfd, new connection on newfd
int is_conected = 0; //bool
int is_receiving = 0; //bool
int bSucces = 0; //bool
int nbytes;
char buf[4097];
WSADATA wsaData;
WSAStartup(MAKEWORD(1,1), &wsaData)
FD_ZERO(&read_fds);// clear the read set
socket()
// loose the "address already in use" error message
// next line forces reusing of the port
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*)&yes, sizeof(int)))
//setting proto , port and IP
bind()
listen()
FD_SET(sockfd, &read_fds); // add the listener to the master set
// keep track of the biggest file descriptor
fdmax = sockfd; // so far, it’s this one
while(1)//CIKAL 1
{
is_conected = 0;
is_receiving = 0; // set them at beginning of the cicle
bSucces = 0;
while(1) //CIKAL 2
{
//next function will return when smth. happens on our sockfd
if (select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1)
{
perror("select");
exit(1);
}
if (FD_ISSET(sockfd, &read_fds)) // we got new coonection
{
if(!is_conected)
{
// handle new connection
accept()
is_conected = 1;// conection enabled
if(newfd > sockfd)
{
fdmax = newfd;
}
FD_SET(newfd, &read_fds); //add newfd to monitor set
}//else i don't accept second conection
}//eof if (FD_ISSET(sockfd));
else if(FD_ISSET(newfd, &read_fds)) //client is sending
{
if ((nbytes = recv(newfd, buf, sizeof buf /sizeof(char), 0)) <= 0)
{
// got error or connection closed by client
printf("LinuxServ: Connection reset by remote side");
FD_CLR(newfd, &read_fds); // remove from master set
close(newfd); // bye!
is_conected = 0;
if (nbytes != 0)
perror("recv");/* някои програми изключват по този начин и
затова щом read() даде грешка затварям връзката! */
break; //must go out from cycle 2
}//eof if (nbytes = recv() <= 0)
else // we got some data from a client
{
buf[nbytes] = '\0'; //terminate the string before any operation
GetDataFromStr(buf)
}//we got some data from client
}
}//KRAY NA CIKAL 2
}//KRAY NA CIKAL 1
return 0;
}
//eof main()===================[/cpp]
Re: Сървърска п-ма не работи оптимално
Това работи, ползвам го от години и служи за копиране на файлове по мрежата:
#include "process.h"
int process_start(void){
struct sockaddr_in addr, addr_cl;
socklen_t addrlen;
struct hostent *hp;
int flags;
char localhost[NAMELEN+1];
printf("Proces query started!\n");
/* Creation of socket*/
if((sockfd == socket(AF_INET,SOCK_STREAM,0))==-1)
p_error("socket",errno,0);
if((gethostname(localhost,NAMELEN)==-1)||(hp = /**(hostent*)*/gethostbyname(localhost))==0)
p_error("getting host name", errno,1);
addr.sin_family = (sa_family_t)hp->h_addrtype; /* AF_INET */
addr.sin_port = htons((uint16_t)PORT);
addr.sin_addr.s_addr = *(in_addr_t *)hp->h_addr;
/*Binding of socket */
if (bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) == -1)
p_error("bind", errno, 1);
if (listen(sockfd,5 == -1))
p_error("listen",errno,1);
if ((flags=fcntl(sockfd,F_GETFL))==-1 ||
fcntl(sockfd,F_SETFL,flags & ~O_NDELAY)==-1)
p_error("fctml",errno,1);
for (;;){
addrlen = sizeof(addr_cl);
if((sockfd_new = accept(sockfd,(struct sockaddr*)&addr_cl, &addrlen)) < 0){
p_error("accept",errno,2);
continue;
}
switch(fork()){
case -1: p_error("fork client", errno,3); continue;
case 0:{
char addrcl[4],filename[256],buf[BUFSIZ];
int cnt, fd;
close(sockfd);
*addrcl = ntohl(addr_cl.sin_addr.s_addr);
if ((cnt = read(sockfd_new, &filename,255)) ==-1)
p_error("read a filename", errno,4);
filename[cnt] = '\0';
if ((fd = open(filename, O_RDONLY)) == -1)
p_error("open",errno,4);
while((cnt = read(fd, &buf, sizeof(buf)))!=0){
if(cnt == -1) p_error("read a file",errno,4);
if(write(sockfd_new, &buf,cnt)!=cnt)
p_error("write",errno,4);
}
shutdown(sockfd_new,2);
close(sockfd_new);
exit(0);
}
close(sockfd_new);
}
}
Между другито за какво е включен winsock ?
Re: Сървърска п-ма не работи оптимално
Не виждам никъде да се преизчислява fdmax след затварянето на сокета. Ако не отваряш други файлдескриптори, просто свали реда вътре в "CIKAL 1".
@klamer: Вероятно идеята е да се мине без fork()
Re: Сървърска п-ма не работи оптимално
@ etg, Sorry забравих за това изискване :
Цитат:
Първоначално публикувано от Scorpion
трябва да направя сървър (ще работи на linux) който приема връзки от
клиенти, обработва ги и щом клиента затвори връзката, да е готов да
приеме следващия.
@Scorpion моята програма е за автоматично сваляне на файлове като може да се свалят няколко едновременно и то различни, съжалявам че не ти върши работа, но при мен работи безотказно вече 2-3 години като обслужва 3-4 клиента
Re: Сървърска п-ма не работи оптимално
Цитат:
Първоначално публикувано от klamer
@ etg, Sorry забравих за това изискване
А, не знам дали има такова изискване, просто предполагам :)
А и не знам какво връща select() при неправилен първи параметър, не ми се е случвало, просто това ми се откроява пред очите.
Re: Сървърска п-ма не работи оптимално
Цитат:
Първоначално публикувано от klamer
Между другито за какво е включен winsock ?
забравил съм да го изтрия, изложих се. За целите на теста: докато заработи го тествам на DevCpp на Win, а като стане ще но махна и ще сложа хедърите на линукс.
моята задача е Win да праща фаилове на линукс, последователно. твоето може и да ми свърши работа, но искам да открия топлата вода сам :)
Цитат:
Първоначално публикувано от etg
Не виждам никъде да се преизчислява fdmax след затварянето на сокета. Ако не отваряш други файлдескриптори, просто свали реда
вътре в "CIKAL 1".
@etg : беше там вътре ;) , но ефекта беше същата грешка. забравих да сложа коментар там, sorry
ВЪПРОС (за да не отварям нов топик): трябва Win да сработва в определен час (веднъж на ден) и преди да съм се заровил в търсен да ви питам: как най-лесно да получа час и да го сравня с друг заложен в кода (Win32API). Благодаря
Re: Сървърска п-ма не работи оптимално
@ Scorpion
here is a list of them from MSDN:
CompareFileTime
DosDateTimeToFileTime
FileTimeToDosDateTime
FileTimeToLocalFileTime
FileTimeToSystemTime
GetFileTime
GetLocalTime
GetSystemTime
GetSystemTimeAdjustment
GetSystemTimeAsFileTime
GetTickCount
GetTimeZoneInformation
LocalFileTimeToFileTime
SetFileTime
SetLocalTime
SetSystemTime
SetSystemTimeAdjustment
SetTimeZoneInformation
SystemTimeToFileTime
SystemTimeToTzSpecificLocalTime
Re: Сървърска п-ма не работи оптимално
благодаря със закъснение.