c套接字编程出错:在accept()之后,程序进入关闭状态。

时间:2014-11-21 13:01:22

标签: c sockets proxy server

我用C创建了一个简单的代理服务器代码。它仅在尝试连接到www.yahoo.com/news.html时才有效

但其他网站没有。(例如google或cnn等)

当程序首先进入'accept()'时,没关系。

所有变量都有自己的值。

但是在'while()'导致第二个'accept()'之后,程序关闭了。

直到那时,变量(sockfd2,newsockfd)仍然有自己的价值。

这很奇怪,因为我之前关闭了他们去()。

我真的不知道为什么我的程序会关闭,为什么它有时会告诉我“地址已经在使用”。

我错过了什么吗? Plz告诉我。

这是代码。

/* 
   A simple server in the internet domain using TCP
   Usage:./server port (E.g. ./server 10000 )
*/
#include <stdio.h>
#include <sys/types.h>   // definitions of a number of data types used in socket.h and netinet/in.h
#include <sys/socket.h>  // definitions of structures needed for sockets, e.g. sockaddr
#include <netinet/in.h>  // constants and structures needed for internet domain addresses, e.g. sockaddr_in
#include <stdlib.h>
#include <strings.h>
#include <netdb.h>      // define structures like hostent

void error(char *msg)
{
    perror(msg);
    exit(1);
}

char *replaceAll(char *s, const char *olds, const char *news) {
  char *result, *sr;
  size_t i, count = 0;
  size_t oldlen = strlen(olds); if (oldlen < 1) return s;
  size_t newlen = strlen(news);


  if (newlen != oldlen) {
    for (i = 0; s[i] != '\0';) {
      if (memcmp(&s[i], olds, oldlen) == 0) count++, i += oldlen;
      else i++;
    }
  } else i = strlen(s);


  result = (char *) malloc(i + 1 + count * (newlen - oldlen));
  if (result == NULL) return NULL;


  sr = result;
  while (*s) {
    if (memcmp(s, olds, oldlen) == 0) {
      memcpy(sr, news, newlen);
      sr += newlen;
      s  += oldlen;
    } else *sr++ = *s++;
  }
  *sr = '\0';

  return result;
}

int main(int argc, char *argv[])
{
    int sockfd, newsockfd; //descriptors rturn from socket and accept system calls
    int sockfd2, newsockfd2; //Socket descriptor
    int portno; // port number
    int portno2, n2;

    socklen_t clilen;

    char buffer[1024];
    char resMsg[2048];
    char bufferForAddr[1024]; 
    char ip[100];

     /*sockaddr_in: Structure Containing an Internet Address*/
    struct sockaddr_in serv_addr, cli_addr;

    struct sockaddr_in serv_addr2;
    struct hostent *server2; //contains tons of information, including the server's IP address
    struct in_addr **addr_list;

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

     /*Create a new socket
       AF_INET: Address Domain is Internet 
       SOCK_STREAM: Socket Type is STREAM Socket */
     sockfd = socket(AF_INET, SOCK_STREAM, 0);
     if (sockfd < 0) 
        error("ERROR opening socket");

    /*browser's port no is 80*/
    portno2 = 80;
    sockfd2 = socket(AF_INET, SOCK_STREAM, 0); //create a new socket
    if (sockfd2 < 0) 
        error("ERROR opening socket");

     bzero((char *) &serv_addr, sizeof(serv_addr));
     portno = atoi(argv[1]); //atoi converts from String to Integer
     serv_addr.sin_family = AF_INET;
     serv_addr.sin_addr.s_addr = INADDR_ANY; //for the server the IP address is always the address that the server is running on
     serv_addr.sin_port = htons(portno); //convert from host to network byte order   

     if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) //Bind the socket to the server address
              error("ERROR on binding");

     listen(sockfd,5); // Listen for socket connections. Backlog queue (connections to wait) is 5

     clilen = sizeof(cli_addr);
     /*accept function: 
       1) Block until a new connection is established
       2) the new socket descriptor will be used for subsequent communication with the newly connected client.
     */
    while(1){

        printf("==========================main========================\n");
         newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
         if (newsockfd < 0) 
              error("ERROR on accept");

         bzero(buffer,1024);

         n = read(newsockfd,buffer,1023); //Read is a block function. It will read at most 255 bytes
         if (n < 0) error("ERROR reading from socket");
            printf("Here is the message1: %s\n",buffer);
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            /*
            get an info about destination site from browser(client)
            */
        printf("Here is the message2: %s\n",buffer);
        char *reqMSG;
        char *address;

        reqMSG = replaceAll(buffer, "HTTP/1.1", "HTTP/1.0");
        reqMSG = replaceAll(reqMSG, "keep-alive", "close");
        //strcat(reqMSG, "\r\nProxy-Connection: keep-alive\r\n");
        strcat(reqMSG,"\r\n");
        //printf("MSG : %s",reqMSG);

        strcpy(bufferForAddr,buffer);
        address = strtok(bufferForAddr+11," ");
        address = strtok(address,"/");
        printf("address : %s\n",address);
        printf("MSG : %s\n",reqMSG);
        /*
        Q2. make a algorithm for filtering about cached site.
        */       
        /*
        if the site is not cached, send the Msg to it's ip address!
        in this section, I need to use functions each called connect, write and read.
        */



        server2 = gethostbyname(address); //takes a string like "www.yahoo.com", and returns a struct hostent which contains information, as IP address, address type, the length of the addresses...
        //get an ip address from hostname
        /*
        addr_list = (struct in_addr **) server2->h_addr_list;
        int i;
        for(i = 0; addr_list[i] != NULL; i++) 
        {
            strcpy(ip , inet_ntoa(*addr_list[i]) );
        }  
*/
        if (server2 == NULL) {
            fprintf(stderr,"ERROR, no such host\n");
            exit(0);
        }

        bzero((char *) &serv_addr2, sizeof(serv_addr2));
        serv_addr2.sin_family = AF_INET; //initialize server's address
        bcopy((char *)server2->h_addr, (char *)&serv_addr2.sin_addr.s_addr, server2->h_length);
        serv_addr2.sin_port = htons(portno2);


        if (connect(sockfd2,(struct sockaddr *)&serv_addr2,sizeof(serv_addr2)) < 0){ //establish a connection to the server
            error("ERROR connecting");
        }
                        //send a REQ MSG from above step!

        //do{
        n2 = write(sockfd2,reqMSG,strlen(reqMSG)); //write to the socket
        if (n2 < 0) {
             error("ERROR writing to socket");
             //break;
         }
        printf("What's wrong : %s\n",reqMSG);
        printf("%s\n",resMsg);
        bzero(resMsg,2047);

       while (n2 = read(sockfd2,resMsg,2047)>0){ //read from the socket
        printf("=================================sub=============================\n");
        if (n2 < 0){ 
             error("ERROR reading from socket");
            //break;
        }
        printf("resMsg : %s\n",resMsg);
        //printf("\nI'm in the loop!\n");
       //}while(1);
            /*
            if I get response Msg to my destination site, I will return it to my source site.
            and wait for closing Msg to browser(client).
            */


         write(newsockfd,resMsg,n2); //NOTE: write function returns the number of bytes actually sent out Ñ> this might be less than the number you told it to send
         if (n < 0) error("ERROR writing to socket");
         bzero(resMsg,2047);
        }

        close(sockfd2);

         /*
            make a log file and save this site!
         */
        //printf("\nip : %s \n",ip);
        close(newsockfd);
     }
     close(sockfd);



     return 0; 
}

1 个答案:

答案 0 :(得分:0)

befor bind尝试

int tr=1;
if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &tr, sizeof(int)) == -1) {
    perror("setsockopt");
 }