socket改-面向连接并发

getservbyname()
将一些服务名转换为熟知的端口号
如HTTP:80

gethostbyname()
域名解析将域名转换称为ip

getprotobyname()
协议号的解析

对于dev c++
分开的代码编译不了。
https://blog.csdn.net/qq_31869107/article/details/81234785

设计一个connectsock过程封装底层代码

//consock.cpp
#include 
#include 
#include 
#include 

#ifdef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif          //写不写都一样winsock.h里有完成的。

void errexit(const char *, ...);   //异常退出函数

SOCKET connectsock(const char * host, const char * service,
                     const char * transport)
{
    struct hostent * phe;   //域名解析将域名解析成ip的返回地址
    struct servent * pse;   //常用端口号函数返回值 存放
    struct protoent * ppe;  //协议号
    struct sockaddr_in sin; //目标地址
    int s, type;            //描述符(windows 叫句柄)和传输类型(UDP/TCP)
    
    memset(&sin, 0, sizeof(sin));   //清0
    sin.sin_family = AF_INET;       //IPv4

    if (pse = getservbyname(service, transport))  //获取服务端口号
        sin.sin_port = pse->s_port;
    else if((sin.sin_port = htons((u_short)atoi(service))) == 0)  //如果是端口,htons转化成网络字节
        errexit("can't get %s service entry\n", service);   //都不是报错退出
    
    if (phe = gethostbyname(host))  //获取域名ip
        memcpy(&sin.sin_addr, phe->h_addr, phe->h_length);  //复制phe的lengh长度到sin
    else if ((sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE) //如果是ip地址 inet_addr十进制的数转化为二进制的数
        errexit("can't get %s host entry\n", host);
    
    if ((ppe = getprotobyname(transport)) == 0) //协议号
        errexit("can't get %s protocol entry\n", transport);

    if (strcmp(transport, "udp") == 0)  
        type = SOCK_DGRAM;
    else
        type = SOCK_STREAM;
    
    s = socket(PF_INET, type, ppe->p_proto); //创建套接字
    if (s == INVALID_SOCKET)
        errexit("can't create socket:%d\n", GetLastError());
    
    if (connect(s, (SOCKADDR *)&sin, sizeof(sin)) == SOCKET_ERROR) //连接服务器
        errexit("can't connect to %s.%s:%d\n", host, service, GetLastError());
    
    return s;
}

connectTCP过程

//conTCP.cpp
#include 
SOCKET connectsock(const char *, const char *, const char *);

SOCKET connectTCP(const char * host , const char * service)
{
    return connectsock(host, service, "tcp");
}

异常处理

//errexit.cpp
#include 
#include 
#include 
#include 

void errexit(const char * format, ...)
{
    va_list args;
    va_start(args, format);
    vfprintf(stderr, format, args);
    va_end(args);
    WSACleanup();
    exit(1);
}

客户端主函数

//TCPdtc.cpp
#include 
#include 
#include 

void TCPdaytime(const char *, const char *);
void errexit(const char *, ...);
SOCKET connectTCP(const char *, const char *);

#define LINELEN 128
#define WSVERS MAKEWORD(2, 0)

int main(int argc, char const *argv[])
{
    const char *host = "localhost";   //目标
    const char *service = "daytime";    //服务
    WSADATA wsadata;
    switch (argc)
    {
    case 1:
        host = "localhost";
        break;
    case 3:
        service = argv[2];
    case 2:
        host = argv[1];
        break;
    default:
        fprintf(stderr, "usage: TCPdaytime");
        exit(1);
    }
    if (WSAStartup(WSVERS, &wsadata) != 0)      //初始化
        errexit("WSASTARTUP, FAILED\n");
    TCPdaytime(host, service);
    WSACleanup();

    return 0;
}

void TCPdaytime(const char * host, const char * service)
{
    char buf[LINELEN + 1];
    SOCKET s;
    int cc;
    s = connectTCP(host, service);

    cc = recv(s, buf, LINELEN, 0);
    while (cc != SOCKET_ERROR && cc > 0)  //tcp是一点一点传输的过来的不是完整的包所以要循环
    {
        buf[cc] = '\0';
        (void)fputs(buf, stdout);
        cc = recv(s, buf, LINELEN, 0);
    }
    closesocket(s);
}

服务器端

//passsock.cpp
#include 
#include 
#include 
void errexit(const char * , ...);

SOCKET passivesock(const char * service, const char * transport, int qlen)
{
    struct servent * pse;
    struct protoent * ppe;
    struct sockaddr_in sin;
    SOCKET s;
    int type;

    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = INADDR_ANY;

    if (pse = getservbyname(service, transport))
        sin.sin_port = (u_short)pse->s_port;
    else if((sin.sin_port = htons((u_short)atoi(service))) == 0)
        errexit("can't get %s\n", service);
    
    if ((ppe = getprotobyname(transport)) == 0)
        errexit("can't get %s", transport);
    
    if (strcmp(transport, "udp") == 0)
        type = SOCK_DGRAM;
    else 
        type = SOCK_STREAM;
    
    s = socket(PF_INET, type, ppe->p_proto);
    if (s == INVALID_SOCKET)
        errexit("can't create socket:%d\n",GetLastError());

    if (bind(s, (SOCKADDR *)&sin, sizeof(sin)) == SOCKET_ERROR)
        errexit("can't bind %s port, %d", service, GetLastError());
    if(type == SOCK_STREAM && listen(s, qlen) == SOCKET_ERROR)
        errexit("can't listen on %s port:%d", service, GetLastError());
        
    return s;
}
//passiveTCP.cpp
#include 

SOCKET passivesock(const char *, const char *, int);

SOCKET passiveTCP(const char * service, int qlen)
{
    return passivesock(service, "tcp", qlen);
}

主程序


#include 
#include 
#include 
#include 

void errexit(const char *, ...);
void TCPdaytimed(SOCKET);
SOCKET passiveTCP(const char *, int);

#define QLEN 5
#define WSVERS MAKEWORD(2, 0)

void main(int argc, char *argv[])
{
    struct sockaddr_in fsin;
    char *service = "daytime";
    SOCKET msock, ssock;
    int alen;
    WSADATA wsadata;

    switch (argc)
    {
    case 1:
        /* code */
        break;
    case 2:
        service = argv[1];
    default:
        errexit("usage:TCPDAYTIMED\n");

    }
    if (WSAStartup(WSVERS, &wsadata) != 0)
        errexit("failed\n");
    msock = passiveTCP(service, QLEN);
    while (1)
    {
        alen = sizeof(SOCKADDR);
        ssock = accept(msock, (SOCKADDR *)&fsin, &alen);
        if (ssock == INVALID_SOCKET)
            errexit("accept %d", GetLastError());
        if (_beginthread((void(*)(void *))TCPdaytimed, 0,
            (void *)ssock) < 0)
        {
            errexit("_beg%s", strerror(errno));
        }
        
    }
        
}

void TCPdaytimed(SOCKET fd)
{
    char * pts;
    time_t now;

    (void)time(&now);
    pts = ctime(&now);
    (void)send(fd, pts, strlen(pts), 0);
    (void)closesocket(fd);
}

出自 : 计算机网络之网尽其用
https://www.icourse163.org/learn/HIT-154005?tid=1206679208#/learn/announce

你可能感兴趣的:(socket改-面向连接并发)