首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >这是如何为一个“你好世界”的套接字编程?

这是如何为一个“你好世界”的套接字编程?
EN

Code Review用户
提问于 2013-05-28 00:46:29
回答 1查看 959关注 0票数 2

我试着用Beej套接字编程指南写了这个。很明显我做错了什么吗?是否存在缓冲区溢出的可能性?分割故障?有什么可能的错误,我没有检查?

或者我做得太过火了?

非常感谢。

代码语言:javascript
复制
/*
 * sk2.c
 *
 *  Created on: May 26, 2013
 *      Author: bharath
 */


#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
#include <regex.h>
#define BUFSIZE 1025

int main(int argC, char *argv[]){
    struct addrinfo hints, *results, *p;
    int status, s,con1, rret;
    char ipstr[INET6_ADDRSTRLEN];
    printf("Bharath's Socket Program\n");
    memset(&hints,0,sizeof hints);
    hints.ai_family=AF_UNSPEC;
    hints.ai_socktype=SOCK_STREAM;
    if (argC<2){
        fprintf(stderr,"No URI given.\n");
        return -1;
    }
    regex_t fqdnParser, resourceParser;
    regmatch_t m;
    char *fqdn, *resource;

    if (!regcomp(&fqdnParser,"^[a-zA-Z0-9.]*",0)){
        char *buff = argv[1];
        if (!regexec(&fqdnParser, argv[1], 1, &m, 0)){
            fqdn=(char*)malloc(m.rm_eo-m.rm_so+1);
            snprintf (fqdn,m.rm_eo-m.rm_so+1,"%.*s \n", m.rm_eo, buff+m.rm_so);
            *(fqdn+m.rm_eo-m.rm_so)=0;
        }else{
            fprintf(stderr,"Bad URI FQDN.\n");
            return -1;
        }
        if (!regcomp(&resourceParser,"/.*$",0)){
            if (!regexec(&resourceParser, argv[1], 1, &m, 0)){
                resource=(char*)malloc(m.rm_eo-m.rm_so+1);
                snprintf (resource,m.rm_eo-m.rm_so+1,"%.*s \n", m.rm_eo, buff+m.rm_so);
                *(resource+m.rm_eo-m.rm_so)=0;
            }
            else{
                resource="/";
            }
            printf("Parsed: [ %s ][ %s ]\n",fqdn,resource);
        }
    }else{
        fprintf(stderr,"RegEx not compiled.\n");
    }
    regfree(&fqdnParser);
    regfree(&resourceParser);
    if ((status=getaddrinfo(fqdn,"http",&hints,&results))!=0){
        fprintf(stderr,"Error: %s\n",gai_strerror(status));
        return -2;
    }
    for(p=results; p!=NULL; p=p->ai_next){
        char *ipver;
        void *addr;
        //ipver=malloc(5);
        if (p->ai_family==AF_INET){
            ipver="IPv4";
            struct sockaddr_in *ipv4=(struct sockaddr_in*)p->ai_addr;
            addr=&(ipv4->sin_addr);
        }else if(p->ai_family==AF_INET6){
            ipver="IPv6";
            struct sockaddr_in6 *ipv6=(struct sockaddr_in6*)p->ai_addr;
            addr=&(ipv6->sin6_addr);
        }
        inet_ntop(p->ai_family,addr,ipstr,sizeof ipstr);
        printf("%s %s\n",ipver, ipstr);
        if ((s=socket(p->ai_family,p->ai_socktype,p->ai_protocol))!=-1){
            if (connect(s,p->ai_addr,p->ai_addrlen) == -1){
                fprintf(stderr,"Error Connecting.");
            }else{
                char *req;
                req=(char*)malloc(25+strlen(resource)+strlen(fqdn));
                strcpy(req,"GET ");
                strcat(req,resource);
                strcat(req," HTTP/1.0\nHost: ");
                strcat(req,fqdn);
                strcat(req,"\n\n");
                //printf("%d | %s",strlen(resource),req);

                void *buf;
                int len,b;
                long int bc=0;
                buf=malloc(BUFSIZE);
                *(char*)(buf+BUFSIZE)=0;
                len=strlen(req);
                b=send(s,req,len,0);
                printf("%d bytes sent\n--------------\n",b);
                printf("%s\n-----------------\n",req);
                b=0;
                do{
                    if(b<BUFSIZE-1){
                        *(char*)(buf+b)=0;
                    }
                    printf("%s",(char*)buf);
                    bc+=b;
                }while ((b=recv(s, buf, BUFSIZE-1, 0))>0);
                close(s);
                printf("\n--------------\n%ld bytes received.",bc);
                free(buf);
                break;
            }
        }else{
            fprintf(stderr,"Socket not created: %d\n",s);
            return -3;
        }
    }
    return 0;
}
EN

回答 1

Code Review用户

回答已采纳

发布于 2013-05-28 15:02:57

我对套接字不太了解,但这里有一些通用的C编程注释:

Bugs

  • 您从未释放() resource的malloc内存。如果您这样做了,那么当您试图释放()该内存时,resource="/";会使程序崩溃。

可能的bug

  • char ipstr[INET6_ADDRSTRLEN];声明一个大小为“字符串长度”的数组是可疑的。您确定这为字符串空终止字符分配了足够的空间吗?
  • (char*)malloc从来没有理由将malloc的结果投到C中,它甚至在C90中也有潜在的危害。您可以在堆栈溢出上找到有关这方面的无数主题。

挑剔的细节和编码风格

  • argC最常见的拼写是小写,argc
  • 最好是自己声明行上的每个变量,使代码更加可读性,并避免像int* ptr1, ptr2; // ptr2 is not a pointer as intended这样的bug。
  • memset(&hints,0,sizeof hints);等应该替换为struct addrinfo hints = { .ai_family=AF_UNSPEC; .ai_socktype=SOCK_STREAM; };,这使得代码更容易阅读,也可能稍微快一些。
  • 理想情况下,应该将return -1替换为stdlib.h中的EXIT_FAILURE。同样,理想情况下,return 0应该被EXIT_SUCCESS取代。
  • 您的代码可以使用更多的空行来分离程序的各个部分。或者更好的是,将这个巨大的main()分割成单独的函数。我认为这会大大改善这个项目。
  • 使用详细的变量命名。像smabc这样的名字使程序难以阅读和理解。
  • 避免在if语句中赋值,很难读懂,如果编译器警告没有正确启用(=当打算使用==时),bug的可能性很小。
  • malloc(25+ ...。神奇的数字25可以被宏(如#define CONST_STRLEN (sizeof("GET ")-1 + sizeof(" HTTP/1.0\nHost: ")-1 + ... + 1) )所取代,这样人们才能真正理解到底发生了什么。
票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/26683

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档