linux下TCP通信的例子

服务器:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netdb.h>
#include "DieWithMessage.h"

#define BUFSIZE 512

static const int MAXPENDING = 5;

int SetupTCPServerSocket(const char *service);
int AcceptTCPConnection(int servSock);
void HandleTCPClient(int clntSocket);
void PrintSocketAddress(const struct sockaddr *address, FILE *stream);

int main(int argc, char *argv[])
{
    if(argc != 2 )
        DieWithUserMessage("Parameter(s)", "<Server Port/Service");

    char *service = argv[1];

    int servSock = SetupTCPServerSocket(service);

    if(servSock < 0)
        DieWithUserMessage("SetupTCPServerSocket() failed", service);

    for(;;)
    {
        int clntSock = AcceptTCPConnection(servSock);

        HandleTCPClient(clntSock);
        close(clntSock);
    }
}


int SetupTCPServerSocket(const char *service)
{
    struct addrinfo addrCriteria;
    memset(&addrCriteria, 0, sizeof(addrCriteria));

    addrCriteria.ai_family = AF_UNSPEC;
    addrCriteria.ai_flags = AI_PASSIVE;
    addrCriteria.ai_socktype = SOCK_STREAM;
    addrCriteria.ai_protocol = IPPROTO_TCP;

    struct addrinfo *servAddr;
    int rtnVal = getaddrinfo(NULL, service, &addrCriteria, &servAddr);
    if(rtnVal != 0)
        DieWithUserMessage("getaddrinfo() failed", gai_strerror(rtnVal));

    int servSock = -1;
    struct addrinfo *addr;
    for(addr=servAddr; addr != NULL; addr=addr->ai_next)
    {
        servSock = socket(servAddr->ai_family, servAddr->ai_socktype, servAddr->ai_protocol);
        if(servSock<0)
            continue;

        if((bind(servSock, servAddr->ai_addr, servAddr->ai_addrlen) == 0) && 
                (listen(servSock, MAXPENDING) == 0))
        {
            struct sockaddr_storage localAddr;
            socklen_t addrSize = sizeof(localAddr);
            if(getsockname(servSock, (struct sockaddr *)&localAddr, &addrSize) < 0)
                DieWithSystemMessage("getsockname() failed");

            fputs("Binding to ", stdout);
            PrintSocketAddress((struct sockaddr *)&localAddr, stdout);
            fputc('\n', stdout);
            break;
        }
        
        close(servSock);
        servSock = -1;

    }

    freeaddrinfo(servAddr);

    return servSock;
}

int AcceptTCPConnection(int servSock)
{
    struct sockaddr_storage clntAddr;
    socklen_t clntAddrLen = sizeof(clntAddr);

    int clntSock = accept(servSock, (struct sockaddr*)&clntAddr, &clntAddrLen);
    if(clntSock < 0)
        DieWithSystemMessage("accept() fail");

    fputs("Handling client ", stdout);
    PrintSocketAddress((struct sockaddr *) &clntAddr, stdout);
    fputc('\n', stdout);

    return clntSock;
}

void HandleTCPClient(int clntSocket)
{
    char buffer[BUFSIZE];
    ssize_t numBytesRcvd = recv(clntSocket, buffer, BUFSIZE, 0);

    if(numBytesRcvd < 0)
        DieWithSystemMessage("recv() failed");

    while(numBytesRcvd > 0)
    {
        ssize_t numBytesSent = send(clntSocket, buffer, numBytesRcvd, 0);
        if(numBytesSent < 0)
            DieWithSystemMessage("send() failed");
        else if(numBytesSent != numBytesRcvd)
            DieWithUserMessage("send()", "send unexpected number of bytes");

        numBytesRcvd = recv(clntSocket, buffer, BUFSIZE, 0);
        if(numBytesRcvd < 0)
            DieWithSystemMessage("recv() failed");
    }

    close(clntSocket);
}


void PrintSocketAddress(const struct sockaddr *address, FILE *stream)
{
    if(address == NULL || stream == NULL)
        return;

    void *numericAddress;
    char addrBuffer[INET6_ADDRSTRLEN];
    in_port_t port;

    switch(address->sa_family)
    {
        case AF_INET:
            numericAddress = &((struct sockaddr_in *)address)->sin_addr;
            port = ntohs(((struct sockaddr_in *)address)->sin_port);
            break;
        case AF_INET6:
            numericAddress = &((struct sockaddr_in6 *)address)->sin6_addr;
            port = ntohs(((struct sockaddr_in6 *)address)->sin6_port);
            break;
        default:
            fputs("[unknown type]", stream);
            return;
    }

    if(inet_ntop(address->sa_family, numericAddress, addrBuffer, sizeof(addrBuffer)) == NULL)
        fputs("[invalid address]", stream);
    else
    {
        fprintf(stream, "%s", addrBuffer);
        if(port != 0)
            fprintf(stream, "-%u", port);
    }
}

客户端:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include "DieWithMessage.h"
#include "TCPClientUtility.c"

#define BUFSIZE 512

int main(int argc, char *argv[])
{
    if(argc < 3 || argc > 4)
    {
        DieWithUserMessage("Parameter(s)", "<Server Address/Name> <Echo Word> [<Server Port/Service]");
    }

    char *server = argv[1];
    char *echoString = argv[2];

    char *service = (argc==4)? argv[3] : "echo";

    int sock = SetupTCPClientSocket(server, service);
    if(sock < 0)
        DieWithUserMessage("SetupTCPClientSocket() failed", "unable to connect");

    size_t echoStringLen = strlen(echoString);

    ssize_t numBytes = send(sock, echoString, echoStringLen, 0);

    if(numBytes < 0)
        DieWithSystemMessage("send() failed");
    else if (numBytes != echoStringLen)
        DieWithUserMessage("send()", "sent unexpected number of bytes");

    unsigned int totalBytesRevd = 0;
    fputs("Received: ", stdout);

    while(totalBytesRevd < echoStringLen)
    {
        char buffer[BUFSIZE];
        numBytes = recv(sock, buffer, BUFSIZE - 1, 0);

        if(numBytes < 0)
            DieWithSystemMessage("recv() failed");
        else if(numBytes == 0)
            DieWithUserMessage("recv()", "connection closed prematurely");

        totalBytesRevd += numBytes;
        buffer[numBytes] = '\0';
        fputs(buffer, stdout);
    }

    fputc('\n', stdout);

    close(sock);
    exit(0); 
}

另外两个文件:

TCPClientUtility.c

#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include "DieWithMessage.h"


int SetupTCPClientSocket(const char *host, const char *service)
{
    struct addrinfo addrCriteria;
    memset(&addrCriteria, 0, sizeof(addrCriteria));

    addrCriteria.ai_family = AF_UNSPEC;
    addrCriteria.ai_socktype = SOCK_STREAM;
    addrCriteria.ai_protocol = IPPROTO_TCP;

    struct addrinfo *servAddr;

    int rtnVal = getaddrinfo(host, service, &addrCriteria, &servAddr);
    if(rtnVal != 0)
        DieWithUserMessage("get addrinfo() failed", gai_strerror(rtnVal));

    int sock = -1;
    struct addrinfo *addr;
    for(addr = servAddr; addr != NULL; addr = addr->ai_next)
    {
        sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
        if(sock <0)
            continue;

        if(connect(sock, addr->ai_addr, addr->ai_addrlen)==0)
            break;

        close(sock);
        sock = -1;
    }

    freeaddrinfo(servAddr);
    return sock;
}

DieWithMessage.h

#ifndef DIE_WITH_MESSAGE
#define DIE_WITH_MESSAGE

#include <stdio.h>
#include <stdlib.h>

void DieWithUserMessage(const char* msg, const char *detail)
{
    fputs(msg, stderr);
    fputs(": ", stderr);
    fputs(detail, stderr);
    fputc('\n', stderr);
    exit(1);
}

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

#endif
原文地址:https://www.cnblogs.com/wouldguan/p/2770773.html