linux套接字编程笔记(二)--简单的TCP套接字应用程序

12 篇文章 0 订阅
8 篇文章 0 订阅

linux套接字编程笔记(二)–简单的TCP套接字应用程序

这里参照linux套接字编程笔记(一)–TCP与UDP提到的流程,编写了一个简易的C语言TCP server和client,主要是留着代码供自己后面参考,否则每次再用C或者C++写还得搜别人的代码,可能还有坑。。。

linux套接字编程笔记(一)–TCP与UDP,链接是http://blog.csdn.net/qq_15437667/article/details/70194698

代码如下

client

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

#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>

#define IP_SIZE             (20)
#define SERVER_LISTEN_PORT  (10000)
#define BUFFER_SIZE (4096)
#define MAX_FILE_NAME_LEN (256)

void tcpClientUploadFile(int sockFd, struct sockaddr_in *serverAddr, char *filePath);

int main(int argc, char *argv[]) {
    int sockFd = 0;
    char serverIP[IP_SIZE];
    struct sockaddr_in serverAddr;

    if (argc == 2) {
        strcpy(serverIP, argv[1]);
    } else if (argc == 1){
        strcpy(serverIP, "127.0.0.1");
    } else {
        printf("error command\n");
        exit(-1);
    }

    //create socket
    sockFd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockFd < 0) {
        printf("create socket failed\n");
        exit(-1);
    }

    /* set serverAddr */
    /* 
    struct sockaddr
    {
        unsigned short sa_family;
        char sa_data[14];
    };

    struct sockaddr_in {
        short            sin_family;       // 2 bytes e.g. AF_INET, AF_INET6
        unsigned short   sin_port;    // 2 bytes e.g. htons(3490)
        struct in_addr   sin_addr;     // 4 bytes see struct in_addr, below
        char             sin_zero[8];     // 8 bytes zero this if you want to
    };

    struct in_addr {
        unsigned long s_addr;          // 4 bytes load with inet_pton()
    };
    */
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(SERVER_LISTEN_PORT);
    serverAddr.sin_addr.s_addr = inet_addr(serverIP);

    //connect the server
    if (connect(sockFd, (struct sockaddr *)&serverAddr, sizeof(struct sockaddr)) < 0) {
        printf("connect failed\n");
        exit(-1);
    }

    printf("connect server success\n");

    //push file
    tcpClientUploadFile(sockFd, &serverAddr, "./test.go");

    close(sockFd);

    return 0;
}

void tcpClientUploadFile(int sockFd, struct sockaddr_in *serverAddr, char *filePath) {
    FILE *stream;
    char buffer[BUFFER_SIZE];
    char filename[MAX_FILE_NAME_LEN];
    int count = 0;

    bzero(buffer, BUFFER_SIZE);
    strcpy(filename, strrchr(filePath, '/') + 1);
    printf("filename is %s\n", filename);
    strncpy(buffer, filename, strlen(filename) > MAX_FILE_NAME_LEN ? MAX_FILE_NAME_LEN : strlen(filename));

    //send filename
    send(sockFd, buffer, BUFFER_SIZE, 0);

    stream = fopen(filePath, "r");
    if (NULL == stream) {
        printf("open file %s failed\n", filePath);
        exit(-1);
    }

    while((count  = fread(buffer, 1, BUFFER_SIZE, stream)) > 0) {
        //printf
        if (send(sockFd, buffer, count, 0) < 0) {
            printf("send failed\n");
            break;
        }

        bzero(buffer, BUFFER_SIZE);
    }

    printf("upload success\n");

    fclose(stream);
}

server

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

#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>

#define IP_SIZE             (20)
#define SERVER_LISTEN_PORT  (10000)
#define BUFFER_SIZE (4096)
#define MAX_FILE_NAME_LEN (256)

void tcpServerDownloadFile (int connFd, struct sockaddr_in *clientAddr, char *fileServerRoot);

int main(int argc, char *argv[]) {
    /*char serverIP[IP_SIZE];

    if (argc >= 2) {

    }*/
    char serverIP[IP_SIZE] = "127.0.0.1";
    int sockFd = 0;
    struct sockaddr_in serverAddr;

    bzero(&serverAddr, sizeof(serverAddr));

    /* create sock */
    sockFd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockFd < 0) {
        perror("sock init failed!\n");
        exit(-1);
    } else {
        printf("create socket success!\n");
    }

    /* set serverAddr */
    /* 
    struct sockaddr
    {
        unsigned short sa_family;
        char sa_data[14];
    };

    struct sockaddr_in {
        short            sin_family;       // 2 bytes e.g. AF_INET, AF_INET6
        unsigned short   sin_port;    // 2 bytes e.g. htons(3490)
        struct in_addr   sin_addr;     // 4 bytes see struct in_addr, below
        char             sin_zero[8];     // 8 bytes zero this if you want to
    };

    struct in_addr {
        unsigned long s_addr;          // 4 bytes load with inet_pton()
    };
    */
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port   = htons(SERVER_LISTEN_PORT);
    serverAddr.sin_addr.s_addr = inet_addr(serverIP);

    //bind
    if (bind(sockFd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) > 0) {
        perror("bind error\n");
        exit(-1);
    } else {
        printf("server bind success!\n");
    }

    //listen
    if(listen(sockFd, 5)) {
        printf("server listen failed, err is %d\n", errno);
        exit(-1);
    } else {
        printf("listen success\n");
    }

    struct sockaddr_in clientAddr;
    socklen_t          length = sizeof(clientAddr);
    int                connFd = 0;

    while (1) {
        //accept
        connFd = accept(sockFd, (struct sockaddr *)&clientAddr, &length);

        if (connFd == -1) {
            printf("accpet err\n");
            continue;
        }

        printf("get connection\n");
        //pull file
        tcpServerDownloadFile(connFd, &clientAddr, "./");

        close(connFd);       
    }


    return 0;
}

void tcpServerDownloadFile (int connFd, struct sockaddr_in *clientAddr, char *fileServerRoot) {
    char buffer[BUFFER_SIZE];
    char filename[MAX_FILE_NAME_LEN];
    char fileServerPath[MAX_FILE_NAME_LEN];
    FILE *stream = NULL;

    int count = 0;
    int dataLen = 0;
    int writeLen = 0;

    bzero(buffer, BUFFER_SIZE);

    count = recv(connFd, buffer, BUFFER_SIZE, 0);

    if (count < 0) {
        printf("recv filename failed!\n");
        exit(1);
    }

    strncpy(filename, buffer, strlen(buffer) > MAX_FILE_NAME_LEN? MAX_FILE_NAME_LEN : strlen(buffer));
    strcpy(fileServerPath, fileServerRoot);
    strcpy(fileServerPath, filename);
    printf("file path:\n %s\n", fileServerPath);

    //open a file
    stream = fopen(fileServerPath, "w");
    if (NULL == stream) {
        printf("create file failed\n");
        exit(-1);
    }
    bzero(buffer, BUFFER_SIZE);

    printf("start recv file\n");

    while((dataLen = recv(connFd, buffer, BUFFER_SIZE, 0)) > 0) {
        //if (dataLen)
        writeLen = fwrite(buffer, sizeof(char), dataLen, stream);
        if (writeLen != dataLen) {
            printf("write error, upload interupt\n");
            exit(-1);
        }

        bzero(buffer, BUFFER_SIZE);
    }

    printf("upload file ok\n");

    fclose(stream);
}

后面扩展成多进程、多线程、通过select、epoll编程、libevent(实际上是封装了linux下的epoll和win下相应接口)都会基于该代码进行微调修改

代码在github路径下
https://github.com/Miss-you/network-program-test.git

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值