Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C &引用;接受;始终返回1,但未关闭任何描述符_C_Sockets_Pthreads - Fatal编程技术网

C &引用;接受;始终返回1,但未关闭任何描述符

C &引用;接受;始终返回1,但未关闭任何描述符,c,sockets,pthreads,C,Sockets,Pthreads,这个程序假装是一个简单的服务器客户端程序,一个线程扫描传入的连接,每个客户端一个新线程建立一个双向通信套接字。 我不关闭stdin、stdout或stderr描述符,但accept始终返回1(stdout),因此文件描述符不是套接字,当我使用send o recv函数时会触发错误,当我使用read或write时会发生错误行为。 谢谢你的阅读 #include <errno.h> #include "../../lib/GC.h" #include <pthread.h>

这个程序假装是一个简单的服务器客户端程序,一个线程扫描传入的连接,每个客户端一个新线程建立一个双向通信套接字。 我不关闭stdin、stdout或stderr描述符,但accept始终返回1(stdout),因此文件描述符不是套接字,当我使用send o recv函数时会触发错误,当我使用read或write时会发生错误行为。 谢谢你的阅读

#include <errno.h>
#include "../../lib/GC.h"
#include <pthread.h>
#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>

#include <netdb.h>
#include <netinet/in.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <poll.h>

#include <string.h>
#include <arpa/inet.h>

typedef struct{
 int socket,stop_service,pos;
 pthread_t tid;
 void *server;
 long client_chunk_max_len;
}tConnectedClient;

typedef struct{
 int socket;
 struct sockaddr_in6 addr;
 struct tSocketOptions{
  int domain,type_and_behavior,protocol;
 }startup_option;
 struct tSocketFDoptions{
  int level,optname,flags;
  void *options;
  socklen_t optlen;
 }socket_option;

 pthread_t tid;
 int stop_service;

 int clients,max_clients;
 tConnectedClient *client;
}tService;

#define CL_BUFFER_SZ 16*1024 //16KB
#define SV_BUFFER_SZ 16*1024 //16KB
#define COMMAND_HELLO 0
#define COMMAND_BYE 1
#define COMMAND_STORE_RESOURCE 2
#define COMMAND_DISPOSE_RESOURCE 3
#define COMMAND_SET_SCENERY 4
#define COMMAND_SET_MOVILE 5
#define COMMAND_MOVE_ITEM 6
#define COMMAND_LIMIT_MOVE_3DITEM 7
#define COMMAND_LIMIT_MOVE_3DITEM_OFF 8
#define COMMAND_LIMIT_NO_MOVE_3DITEM_OFF 9

typedef struct{
 int socket;
 struct sockaddr_in6 addr;
 struct tSocketOptions startup_option;
 char *server_ip;
 bool connected;
 long server_chunk_max_len;
 char client_rcv_data[CL_BUFFER_SZ];
}tClient;

const char say_ok[]={1,0,0,0,0,0,0,0,'+'};

void *client_handler(tConnectedClient *c){
 //TODO gestionar peticiones
 struct pollfd socket_poll={
  fd:c->socket,
  events:POLLIN,
  revents:0
 };
 tService *s=(tService*)c->server; 
 char *buffer=(char*)malloc(SV_BUFFER_SZ);
 int bytes_read,c_socket=c->socket,resources_loaded=0;
 void **resource;
 printf("[INFO]Client tid %d ready on socket %d...\n",c->tid,c_socket);
 int err_lvl;
 do{
  if(err_lvl=poll(&socket_poll,1,10000)>0){
   bytes_read=read(c_socket,buffer,SV_BUFFER_SZ);/*DEBUG*/printf("[DEBUG]bytes_read=%d command=%d len=%d\n",bytes_read,buffer[0],((long*)&buffer[1])[0]);//Reads from descriptor 1, not from "socket"
   if(bytes_read<0){
    printf("Error listening client:\n\t");
    switch(errno){
    case EAGAIN: printf("EAGAIN or EWOULDBLOCK\n");break;
    case EBADF: printf("EBADF\n");break;
    case ECONNREFUSED: printf("ECONNREFUSED\n");break;
    case EFAULT: printf("EFAULT\n");break;
    case EINTR: printf("EINTR\n");break;
    case EINVAL: printf("EINVAL\n");break;
    case ENOMEM: printf("ENOMEM\n");break;
    case ENOTCONN: printf("ENOTCONN\n");break;
    case ENOTSOCK: printf("ENOTSOCK\n");break;
    }
   }else
   switch(buffer[0]){
   case COMMAND_HELLO:{c->client_chunk_max_len=((long*)&buffer[1])[0]; long server_chunk_size=SV_BUFFER_SZ; write(c_socket,&server_chunk_size,sizeof(long));/*DEBUG*/printf("[DEBUG]client_chunk_max_len=%dbytes\n",c->client_chunk_max_len);}break;
   case COMMAND_BYE: c->stop_service=-1; write(c_socket,say_ok,9); break;
   case COMMAND_STORE_RESOURCE:

   break;
   default: printf("Unknow command “%d” from client side\n",buffer[0]);
   }
  }
 }while(!c->stop_service);
 int c_pos;
 s->client[c_pos=c->pos]=s->client[--s->clients];
 s->client[s->clients].pos=c_pos;
 free(buffer);
 printf("[INFO]Client tid %d shutdown\n",c->tid);
 pthread_exit(NULL);
}

void *server_listener(tService *s){//Here is where error happens...
 struct pollfd socket_poll={
  fd:s->socket,
  events:POLLIN,
  revents:0
 };

 /*setsockopt(s->socket=socket(s->startup_option.domain,s->startup_option.type_and_behavior,s->startup_option.protocol),
            s->socket_option.level,s->socket_option.optname,s->socket_option.options,s->socket_option.optlen);
 bind(s->socket,(struct sockaddr*)&s->addr,sizeof(struct sockaddr_in6));
 listen(s->socket,s->max_clients);*///Move init inside does not work...

 int err_lvl;
 do{
  if(err_lvl=poll(&socket_poll,1,10000)>0){
   if(s->clients<s->max_clients){
    int cln=s->clients;
    if(s->client[cln].socket=accept(s->socket,NULL,NULL)>=0){printf("[DEBUG]client socket is %d\n",s->client[cln].socket);//This "accept" always returns 1, but no descriptor has been closed.
     s->client[cln].stop_service=0;
     s->client[cln].pos=cln;
     s->clients++;
     pthread_create(&s->client[cln].tid,NULL,(void*(*)(void*))client_handler,&s->client[cln]);
     printf("[INFO]New incoming client, current load: %d/%d\n",s->clients,s->max_clients);
    }else printf("[WARNING]Error accepting client, no data available? (0x%X)\n",errno);
   }else printf("[INFO]Too many clients, only up to %d allowed, current is %d rejecting...\n",s->max_clients,s->clients);
  }else{
    if(err_lvl==0)printf("[INFO]Server waiting for clients time timeout, retrying...\n");
    else switch(errno){case EFAULT:printf("[WARNING]Server error: EFAULT\n");break;
                       case EINTR:printf("[WARNING]Server error: EINTR\n");break;
                       case EINVAL:printf("[WARNING]Server error: EINVAL\n");break;
                       case ENOMEM:printf("[WARNING]Server error: ENOMEM\n");break;
                      }
   }
 }while(!s->stop_service);
 printf("[INFO]Server thread quits, good bye!!\n");
 for(err_lvl=0;err_lvl<s->clients;err_lvl++){
  atomic_store(&s->client[err_lvl].stop_service,-1);
  pthread_join(s->client[err_lvl].tid,NULL);
 }
 pthread_exit(NULL);
}

tService *setup_service(const char *opt){//TODO config string
 tService *service=(tService*)malloc(sizeof(tService));
 memset(service,0,sizeof(tService));
 service->startup_option.domain=AF_INET6;
 service->startup_option.type_and_behavior=SOCK_STREAM|SOCK_NONBLOCK;
 service->startup_option.protocol=0;

 service->addr.sin6_family=AF_INET6;
 service->addr.sin6_port=htons(5000);
 service->addr.sin6_addr=in6addr_any;

 service->socket_option.options=malloc(service->socket_option.optlen=sizeof(int));
 ((int*)service->socket_option.options)[0]=1;
 service->socket_option.level=SOL_SOCKET;
 service->socket_option.optname=SO_REUSEADDR;

 service->max_clients=2;
 memsetb(service->client=(tConnectedClient*)malloc(sizeof(tConnectedClient)*service->max_clients),0,sizeof(tConnectedClient)*service->max_clients);
 int c=0;for(;c<service->max_clients;c++)service->client[c].server=service;
 return service;
}

void launch_server(tService *service){
 setsockopt(service->socket=socket(service->startup_option.domain,service->startup_option.type_and_behavior,service->startup_option.protocol),
            service->socket_option.level,service->socket_option.optname,service->socket_option.options,service->socket_option.optlen);
 bind(service->socket,(struct sockaddr*)&service->addr,sizeof(struct sockaddr_in6));
 listen(service->socket,service->max_clients);
 pthread_create(&service->tid,NULL,(void*(*)(void*))server_listener,service);
}

int main(int argc,char **argv){
 tService *service=setup_service(NULL);
 launch_server(service);
 printf("[INFO]Server launched...\n");
 getchar();
 atomic_store(&service->stop_service,-1);
 pthread_join(service->tid,NULL);
 printf("[INFO]Server shutdown\n");
 close(service->socket);
 return 0;
}
#包括
#包括“../../lib/GC.h”
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
类型定义结构{
int插座,停止服务,pos;
pthread_t tid;
void*服务器;
长客户端\u块\u最大长度;
}t连接的客户端;
类型定义结构{
int插座;
6地址中的结构sockaddr_;
结构tSocketOptions{
int域,类型和行为,协议;
}启动选项;
结构tSocketFDoptions{
int级别、optname、标志;
作废*期权;
索克伦·奥普特伦;
}插座(u)选件;;
pthread_t tid;
int stop_服务;
int客户端,max_客户端;
t连接的客户端*客户端;
}t服务;
#定义CL_缓冲区_SZ 16*1024//16KB
#定义SV_BUFFER_SZ 16*1024//16KB
#定义命令\u HELLO 0
#定义命令1
#定义命令存储资源2
#定义命令\u DISPOSE\u资源3
#定义命令\u设置\u场景4
#定义命令集移动5
#定义命令\u移动\u项目6
#定义命令\限制\移动\项目7
#定义命令\u限制\u移动\u 3项目\u关闭8
#定义命令\u限制\u禁止\u移动\u 3DITEM\u关闭9
类型定义结构{
int插座;
6地址中的结构sockaddr_;
struct tSocketOptions启动选项;
字符*服务器ip;
布尔连接;
长服务器\u块\u最大\u长度;
char client_rcv_data[CL_BUFFER_SZ];
}客户;
const char say_ok[]={1,0,0,0,0,0,0,'+'};
void*客户端处理程序(tConnectedClient*c){
//待办事项
结构pollfd套接字\u poll={
fd:c->socket,
事件:POLLIN,
复仇者:0
};
t服务*s=(t服务*)c->server;
char*buffer=(char*)malloc(SV_buffer_SZ);
int bytes\u read,c\u socket=c->socket,resources\u load=0;
无效**资源;
printf(“[INFO]客户端tid%d在套接字%d上准备就绪…\n”,c->tid,c_套接字);
内部错误;
做{
如果(err_lvl=poll(&socket_poll,110000)>0){
bytes_read=read(c_socket,buffer,SV_buffer_SZ);/*DEBUG*/printf(“[DEBUG]bytes_read=%d命令=%d len=%d\n”,bytes_read,buffer[0],((long*)&buffer[1])[0]);//从描述符1读取,而不是从“socket读取
如果(bytes_readclient_chunk_max_len=((long*)和buffer[1])[0];long server_chunk_size=SV_buffer_SZ;write(c_socket,&server_chunk_size,sizeof(long))/*DEBUG*/printf(“[DEBUG]client_chunk_max_len=%dbytes\n”,c->client_chunk_max_len)}break;
case命令\u BYE:c->stop\u service=-1;写入(c\u socket,说\u ok,9);中断;
案例命令存储资源:
打破
默认值:printf(“来自客户端的未知命令“%d”,缓冲区[0]);
}
}
}而(!c->停止服务);
国际货币基金组织;
s->client[c_pos=c->pos]=s->client[--s->clients];
s->client[s->clients].pos=c_pos;
自由(缓冲);
printf(“[INFO]客户端tid%d关闭\n”,c->tid);
pthread_exit(NULL);
}
void*server\u监听器(tService*s){//这里是发生错误的地方。。。
结构pollfd套接字\u poll={
fd:s->socket,
事件:POLLIN,
复仇者:0
};
/*setsockopt(s->socket=socket(s->startup_option.domain,s->startup_option.type_and_behavior,s->startup_option.protocol),
s->socket\u option.level,s->socket\u option.optname,s->socket\u option.options,s->socket\u option.optlen);
绑定(s->socket,(struct sockaddr*)和s->addr,sizeof(struct sockaddru in6));
侦听(s->socket,s->max_clients);*///在内部移动init不起作用。。。
内部错误;
做{
如果(err_lvl=poll(&socket_poll,110000)>0){
if(s->clientsmax\u客户端){
int cln=s->clients;
如果(s->client[cln].socket=accept(s->socket,NULL,NULL)>=0){printf(“[DEBUG]client socket是%d\n”,s->client[cln].socket);//此“accept”始终返回1,但未关闭任何描述符。
s->客户端[cln]。停止服务=0;
s->client[cln].pos=cln;
s->clients++;
pthread_create(&s->client[cln].tid,NULL,(void*(*)(void*)client_处理程序,&s->client[cln]);
printf(“[INFO]新传入的客户端,当前加载:%d/%d\n”,s->clients,s->max\u clients);
}else printf(“[警告]接受客户端时出错,没有可用数据?(0x%X)\n”,errno);
}else printf(“[INFO]客户端太多,最多允许%d个,当前是%d个拒绝…\n”,s->max\u客户端,s->clients);
}否则{
如果(err_lvl==0)printf(“[INFO]服务器等待客户端超时,正在重试…\n”);
else开关(errno){case EFAULT:printf(“[WARNING]Server error:EFAULT\n”);中断;
案例EINTR:printf(“[警告]服务器错误:EINTR\n”);中断;
案例EINVAL:printf(“[警告]服务器错误:EINVAL\n”);中断;
案例ENOMEM:printf(“[警告]服务器错误:ENOMEM\n”);中断;
}
}
}而(!s->停止服务);
printf(“[INFO]服务器线程退出,再见!!\n”);
for(err_lvl=0;err_lvlclients;err_lvl++){
原子存储(&s->客户端[err\u lvl]。停止服务,-1);
pthread_join(s->client[err_lvl].tid,NULL);
}
pthread_exit(NULL);
}
t服务*setup\u服务(const char*opt){//TODO配置字符串
t服务*服务=(t服务*)malloc(sizeof(t服务));
memset(服务,0,sizeof(tService));
服务->启动选项。域=AF\u INET6;
服务->启动选项。类型和行为=SOCK\u STREAM | SOCK\u NONBLOCK;
服务->启动选项。协议=0;
服务->地址sin6\u family=AF\u INET6;
服务->地址sin6\u端口=htons(5000);
服务->地址sin6\u addr=in6addr\u any;
service->socket_option.options=malloc(service->socket_option.optlen=sizeof(int));
((int*)服务->套接字_选项.options)[0]=1;
服务->插座\u选项。级别=SOL\u插座;
service->socket\u option.optname=SO\u REUSEADDR;
服务->最大客户数=2;
memsetb(服务->客户端=(tConnectedClient*)malloc(sizeof(tConnectedClient)*服务->最大客户端),0,sizeof(tConnectedClient)*服务->最大客户端);
int c=0;对于(;cmax_clients;c++)服务->客户端[c]。服务器=服务;
回程服务;
}
无效启动服务器(tService*se
a = b >= 0;
s->client[cln].socket = accept(s->socket,NULL,NULL);
if ( s->client[cln].socket >= 0 ) …