0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

實(shí)現(xiàn)TCP的C代碼封裝(含代碼)

嵌入式應(yīng)用開(kāi)發(fā) ? 來(lái)源:嵌入式應(yīng)用開(kāi)發(fā) ? 作者:嵌入式應(yīng)用開(kāi)發(fā) ? 2022-09-28 16:03 ? 次閱讀
poYBAGMz_0OAD2rQAACgyioMl6c244.png

tcp_socket.h:

#ifndef TCP_SCOKET_H
#define TCP_SCOKET_H

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define MAX_CONNECT_NUM 10

int tcp_init(const char* ip, int port);
int tcp_accept(int sfd);
int tcp_connect(const char* ip, int port);
int tcp_nonblocking_recv(int conn_sockfd, 
                         void *rx_buf, 
                         int buf_len, 
                         int timeval_sec, 
                         int timeval_usec);
int tcp_blocking_recv(int conn_sockfd, void *rx_buf, uint16_t buf_len);
int tcp_send(int conn_sockfd, uint8_t *tx_buf, uint16_t buf_len);
void tcp_close(int sockfd);

#endif

tcp_socket.c:

#include "tcp_socket.h"

int tcp_init(const char* ip, int port)
{
    int optval = 1; 
    int server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd < 0)
    {
        perror("socket");
        return -1;
    }

    /* 解除端口占用 */
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0)
 {
  perror("setsockoptn");
  return -1;
 }

    struct sockaddr_in server_addr;
    bzero(&server_addr, sizeof(struct sockaddr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    if (NULL == ip)
    {
        server_addr.sin_addr.s_addr = htonl(INADDR_ANY); 
    }
    else
    {
        server_addr.sin_addr.s_addr = inet_addr(ip); 
    }

    if (bind(server_fd, (struct sockaddr*)&server_addr,sizeof(struct sockaddr)) < 0)
    {
        perror("bind");
        close(server_fd);
        return -1;
    }

    if(listen(server_fd, MAX_CONNECT_NUM) < 0)
    {
        perror("listen");
        close(server_fd);
        return -1;
    }

    return server_fd;
}

int tcp_accept(int server_fd)
{
    struct sockaddr_in client_addr = {0};
    int addrlen = sizeof(struct sockaddr);
    int new_fd = accept(server_fd, (struct sockaddr*) &client_addr, &addrlen);
    if(new_fd < 0)
    {
        perror("accept");
        close(server_fd);
        return -1;
    }
    
    return new_fd;
}

int tcp_connect(const char *ip, int port)
{
    int server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd < 0)
    {
        perror("socket");
        return -1;
    }

    struct sockaddr_in server_addr;
    bzero(&server_addr, sizeof(struct sockaddr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    server_addr.sin_addr.s_addr = inet_addr(ip);

    if (connect(server_fd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr)) < 0)
    {
        perror("connect");
        close(server_fd);
        return -1;
    }

    return server_fd;
}

int tcp_nonblocking_recv(int conn_sockfd, void *rx_buf, int buf_len, int timeval_sec, int timeval_usec)
{
 fd_set readset;
 struct timeval timeout = {0, 0};
 int maxfd = 0;
 int fp0 = 0;
 int recv_bytes = 0;
 int ret = 0;
 
 timeout.tv_sec = timeval_sec;
 timeout.tv_usec = timeval_usec;
 FD_ZERO(&readset);           
 FD_SET(conn_sockfd, &readset);         

 maxfd = conn_sockfd > fp0 ? (conn_sockfd+1) : (fp0+1);    

 ret = select(maxfd, &readset, NULL, NULL, &timeout); 
 if (ret > 0) 
    {
  if (FD_ISSET(conn_sockfd, &readset)) 
        {
   if ((recv_bytes = recv(conn_sockfd, rx_buf, buf_len, MSG_DONTWAIT))== -1) 
            {
    perror("recv");
    return -1;
   }
  }
 } 
    else 
    {
  return -1;
 }
 
 return recv_bytes;
}

int tcp_blocking_recv(int conn_sockfd, void *rx_buf, uint16_t buf_len)
{
    return recv(conn_sockfd, rx_buf, buf_len, 0);
}

int tcp_send(int conn_sockfd, uint8_t *tx_buf, uint16_t buf_len)
{
    return send(conn_sockfd, tx_buf, buf_len, 0);
}

void tcp_close(int sockfd)
{
    close(sockfd);
}

x下面測(cè)試代碼:

#include "tcp_socket.h"

int main(int argc, char **argv)
{
    printf("==================tcp server==================n");
    int server_fd = tcp_init(NULL, 4321);
    if (server_fd < 0)
    {
        printf("tcp_init error!n");
        exit(EXIT_FAILURE);
    }

    int client_fd = tcp_accept(server_fd);
    if (client_fd < 0)
    {
        printf("tcp_accept error!n");
        exit(EXIT_FAILURE);
    }

    while (1)
    {
        char buf[128] = {0};
        
        int recv_len = tcp_blocking_recv(client_fd, buf, sizeof(buf));
        if (recv_len <= 0)
        {
            printf("recv error!n");
            tcp_close(client_fd);
            tcp_close(server_fd);
            exit(EXIT_FAILURE);
        }
        printf("recv : %sn", buf);

        int send_len = tcp_send(client_fd, buf, strlen(buf));
        if (send_len <= 0)
        {
            printf("send error!n");
            tcp_close(client_fd);
            tcp_close(server_fd);
            exit(EXIT_FAILURE);  
        }
        else
        {
            printf("send success! send: %s, send_len: %dn", buf, send_len);
        }
    }
    tcp_close(server_fd);

    return 0;
}

tcp_client.c:

#include "tcp_socket.h"

int main(int argc, char **argv)
{
    printf("==================tcp cient==================n");
    if (argc < 3)
    {
        printf("usage:./tcp_client ip portn");
        exit(EXIT_FAILURE);
    }

    char ip_buf[32] = {0};
    int port = 0;

    memcpy(ip_buf, argv[1], strlen(argv[1]));
    port = atoi(argv[2]);

    int server_fd = tcp_connect(ip_buf, port);
    if (server_fd < 0)
    {
        printf("tcp_connect error!n");
        exit(EXIT_FAILURE);
    }

    while (1)
    {
        char buf[128] = {0};
        if (scanf("%s", buf))
        {
            int send_len = tcp_send(server_fd, buf, strlen(buf));
            if (send_len <= 0)
            {
                printf("tcp_send error!n");
                tcp_close(server_fd);
                exit(EXIT_FAILURE);  
            }
            else
            {
                printf("send success! send: %s, send_len: %dn", buf, send_len);
            }

            bzero(buf, sizeof(buf));
            int recv_len = tcp_blocking_recv(server_fd, buf, sizeof(buf));
            if (recv_len <= 0)
            {
                printf("tcp_blocking_recv error!n");
                tcp_close(server_fd);
                exit(EXIT_FAILURE);
            }
            printf("recv : %sn", buf);
        } 
    }

    return 0;
}
聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • TCP
    TCP
    +關(guān)注

    關(guān)注

    8

    文章

    1347

    瀏覽量

    78934
  • C代碼
    +關(guān)注

    關(guān)注

    1

    文章

    89

    瀏覽量

    14270
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    基于MCS-51單片機(jī)的點(diǎn)陣屏實(shí)現(xiàn)禮花功能(代碼

    電子發(fā)燒友網(wǎng)原創(chuàng):本文是基于MCS-51單片機(jī)的點(diǎn)陣屏實(shí)現(xiàn)禮花功能(代碼和功能實(shí)現(xiàn)圖)
    發(fā)表于 08-08 14:07 ?7334次閱讀
    基于MCS-51單片機(jī)的點(diǎn)陣屏<b class='flag-5'>實(shí)現(xiàn)</b>禮花功能(<b class='flag-5'>含</b>源<b class='flag-5'>代碼</b>)

    TCP 28J60模塊代碼分享!

    C51代碼,控制28J60模塊實(shí)現(xiàn)了部分網(wǎng)絡(luò)傳輸功能。有點(diǎn)亂。TCP_28J60.zip (430.77 KB )
    發(fā)表于 09-18 21:34

    怎么使具體實(shí)現(xiàn)代碼不可見(jiàn)實(shí)現(xiàn)函數(shù)的封裝

    如何實(shí)現(xiàn)函數(shù)的封裝,即能讓別人調(diào)用,但是看不到具體的實(shí)現(xiàn)代碼。舉個(gè)例子,一個(gè)開(kāi)源項(xiàng)目,要把代碼公布出去,但是代碼中有些比較敏感的部分不想讓別
    發(fā)表于 03-12 22:18

    流水燈電路(源程序代碼)

    流水燈電路(源程序代碼)
    發(fā)表于 09-28 12:16 ?2351次閱讀

    嘀聲報(bào)警信號(hào)輸出試驗(yàn)(C語(yǔ)言源程序代碼)

    嘀聲報(bào)警信號(hào)輸出試驗(yàn)(C語(yǔ)言源程序代碼) 這一課,我們將學(xué)習(xí)如何控制蜂鳴器的聲音輸出,這一課我們只輸出
    發(fā)表于 08-09 10:48 ?3389次閱讀

    一個(gè)按鍵控制的10級(jí)變速跑馬燈試驗(yàn)(源程序C語(yǔ)言代碼)

    一個(gè)按鍵控制的10級(jí)變速跑馬燈試驗(yàn)(源程序C語(yǔ)言代碼) 在本課中,我們要用一個(gè)按鍵來(lái)實(shí)現(xiàn)
    發(fā)表于 08-09 23:20 ?3378次閱讀

    CC代碼精髓

    CC代碼精髓,有需要的朋友可以下來(lái)看看。
    發(fā)表于 05-20 14:28 ?40次下載

    C標(biāo)準(zhǔn)庫(kù)源代碼

    標(biāo)準(zhǔn)C語(yǔ)言庫(kù)函數(shù)代碼,編程是可參考源代碼。
    發(fā)表于 07-04 17:31 ?21次下載

    卡爾曼濾波簡(jiǎn)介及其實(shí)現(xiàn)(附C代碼)

    卡爾曼濾波算法介紹,公式實(shí)現(xiàn),后面附有公式的實(shí)現(xiàn)代碼。封裝函數(shù)。
    發(fā)表于 12-17 17:22 ?40次下載

    DSP編程技巧之鏈接匯編代碼C_C++代碼

    在DSP的開(kāi)發(fā)中,常用的算法都可以用C/C++代碼來(lái)高效實(shí)現(xiàn)。但是對(duì)一些特殊寄存器的讀寫(xiě),例如某些CPU寄存器的讀寫(xiě),因?yàn)?b class='flag-5'>C/
    發(fā)表于 10-18 09:47 ?7次下載
    DSP編程技巧之鏈接匯編<b class='flag-5'>代碼</b>與<b class='flag-5'>C_C</b>++<b class='flag-5'>代碼</b>

    基于單片機(jī)AT89C52和DS1302的溫度時(shí)間顯示方案代碼程序

    電子發(fā)燒友網(wǎng)站提供《基于單片機(jī)AT89C52和DS1302的溫度時(shí)間顯示方案代碼程序.zip》資料免費(fèi)下載
    發(fā)表于 01-02 11:34 ?17次下載

    4個(gè)重要算法C語(yǔ)言實(shí)現(xiàn)代碼

    4個(gè)重要算法C語(yǔ)言實(shí)現(xiàn)代碼
    發(fā)表于 06-10 08:00 ?12次下載

    使用C語(yǔ)言實(shí)現(xiàn)靜態(tài)網(wǎng)頁(yè)的代碼免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是使用C語(yǔ)言實(shí)現(xiàn)靜態(tài)網(wǎng)頁(yè)的代碼免費(fèi)下載。
    發(fā)表于 11-22 16:20 ?2次下載

    UDP及TCP通信的程序設(shè)計(jì)和源代碼免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是UDP及TCP通信的程序設(shè)計(jì)和源代碼免費(fèi)下載。
    發(fā)表于 01-08 15:12 ?37次下載
    UDP及<b class='flag-5'>TCP</b>通信的程序設(shè)計(jì)和源<b class='flag-5'>代碼</b>免費(fèi)下載

    在VS上配置MPI教程(代碼

    在VS上配置MPI教程(代碼
    發(fā)表于 01-17 11:24 ?1次下載