c - 在 c 中使用带套接字的线程

标签 c sockets pthreads

我有一个程序,它为每次对服务器的调用创建一个线程。它编译没有错误但是它永远不会进入 printf('before while') 语句但是它确实通过了绑定(bind)

#include <stdio.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <strings.h>    
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <pthread.h>
#include <fcntl.h>
#include <dirent.h> 

#define BufferSize 1024 // for parsing request
#define BIG_ENUF 4096 // For request header

void error(char *); // prototype for quick error exit
void *connection_handler(void * newsockfd);

int main(int argc, char *argv[]) // arv[1] has port #
{

    // We Have Ourselves Some Declarations Old School
 int sockfd, newsockfd, portno, clilen,Connect_Count=0;
 int BufferNdx,n ;// workaday subscripts 
 char * TmpBuffer, *SavePtr, *FileName;
 char * GetToken;
 FILE * F;  // for streaming file when GET served
 struct stat S;// to find file length 
 struct sockaddr_in serv_addr, cli_addr;
 pthread_t tid; 

     if (argc < 2) {  // looking for port # 
         fprintf(stderr,"ERROR, no port provided\n");
         exit(1);
     }

     sockfd = socket(AF_INET, SOCK_STREAM, 0);
     // specifies TCP IP flow 
     if (sockfd < 0) 
        error("ERROR opening socket");
     memset( (char *) &serv_addr, 0, sizeof(serv_addr));
     // Now fill the zeroed server structure // 
     // consistent with socket setup 
     portno = atoi(argv[1]);
     serv_addr.sin_family = AF_INET;  
     serv_addr.sin_addr.s_addr = INADDR_ANY;
     serv_addr.sin_port = htons(portno); // proper byte order
    if (bind(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) {
                    perror("ERROR on binding");
            }

    GetToken = strtok_r(TmpBuffer," ",&SavePtr); 
    printf("before while\n");
    listen(sockfd,5);
    while (Connect_Count < 10) // Limit on Number of Connections
    {

      clilen = sizeof(cli_addr);
      newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
    // listen blocks until someone knocks and when we accept 

  // the client structure is filled by accept 
     if (newsockfd < 0) // exit server if bad accept 
          error( "ERROR on accept");
       Connect_Count++;
     printf("%d\n",Connect_Count ); 
    if(pthread_create(&tid, NULL, connection_handler,(void *)newsockfd )<0){
        perror("could not create thread");
        return 1;
    }
    }
   pthread_exit(NULL);
// Now close up this client's shop 
     close(newsockfd);
     return 0; 
}





void *connection_handler(void* newsock)
{
    int newsockfd = (int) newsock;
    char buffer[BufferSize];
    char * BigBuffer;
    char * TmpBuffer, *SavePtr, *FileName, *GetToken;
    int n;
    struct stat S;
    memset(buffer, 0,BufferSize);
    FILE * F;
     n = read(newsockfd,buffer,BufferSize-1); // This leaves null at end
    if (n < 0) error("ERROR reading from socket");

     printf("%s\n",(TmpBuffer=strtok_r(buffer,"\n",&SavePtr)));
     GetToken = strtok_r(TmpBuffer," ",&SavePtr); 
     printf("%s\n",GetToken); 
     GetToken = strtok_r(NULL," ",&SavePtr); 
     printf("%s After Get\n",GetToken); // file name token begins '/'
     GetToken++; // Point to first character of actual file name 
    // now open the file and send it to client ? 
     if ((F =  fopen(GetToken,"r")) == NULL) error("Bad\n");
    else printf("Good\n"); 
        int FileSize;
    if ((fstat(fileno(F),&S)==-1)) error("failed fstat\n"); // Need file size 
    FileSize = S.st_size;
// Looks ok -- now let's write the request header
 // Let's just fill a buffer with header info using sprintf()           
    char Response[BIG_ENUF];int HeaderCount=0;
    HeaderCount=0;//Use to know where to fill buffer with sprintf 
        HeaderCount+=sprintf( Response+HeaderCount,"HTTP/1.0 200 OK\r\n");
        HeaderCount+=sprintf( Response+HeaderCount,"Server: Flaky Server/1.0.0\r\n");
        HeaderCount+=sprintf( Response+HeaderCount,"Content-Type: image/jpeg\r\n");
        HeaderCount+=sprintf( Response+HeaderCount,"Content-Length:%d\r\n",FileSize);
 // And finally to delimit header
        HeaderCount+=sprintf( Response+HeaderCount,"\r\n"); 
        // Let's echo that to stderr to be sure ! 
        fprintf(stderr,"HeaderCount %d and Header\n",HeaderCount);
        write(STDERR_FILENO, Response, HeaderCount);
        write(newsockfd,Response,HeaderCount); // and send to client
// Now Serve That File in one write to socket
        BigBuffer = malloc(FileSize+2);// Just being OCD -- Slack is 2
        fread(BigBuffer,1,FileSize,F);
        write(newsockfd,BigBuffer,FileSize);
        free(BigBuffer); 
    pthread_exit(NULL);
    return NULL;
}





// Bad Error routine 
void error(char *msg)
{
    perror(msg);
    exit(1);
}

我不确定为什么这会成为一个问题,因为它在我拥有的流程版本中工作。如果有任何改变,我正在使用 gcc -pthread filename.c 进行编译。

最佳答案

这一行 GetToken = strtok_r(TmpBuffer,"",&SavePtr); 似乎是个问题,因为 TmpBuffer 是一个指向 char 的指针,它没有指向任何内容。 ..

将其注释掉,或分配一些内存,填充它,并将其分配给 TmpBuffer

关于c - 在 c 中使用带套接字的线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29959272/

相关文章:

c - 将变量传递给另一个可变参数函数[专家版]

c - accept() block (挂起连接时)

java - Ruby(服务器)- Java(客户端)连接错误

c - 在多线程程序中执行另一个程序

multithreading - 我可以使用 pthreads 分配每个线程索引吗?

c - Sys V ABI 规范(i386 和 AMD64)中描述的标准 "Function Calling Sequence"是否适用于静态 C 函数?

在 C 中释放内存的说明

c - 为什么通过直接赋值复制结构会失败?

arrays - 如何在D中使用动态数组进行UDP接收?

linux - pthread_rwlockattr_getkind_np() 是否仅返回使用 pthread_rwlockattr_setkind_np 设置的标志?