网络通讯-Socket-TCP-demo(C语言版)

本文详细介绍了如何使用C语言实现TCP服务器和客户端。服务器端包括创建Socket、绑定地址和端口、监听连接、接收和发送数据以及关闭连接的步骤。客户端则简化了流程,主要关注连接服务器和收发数据。示例代码清晰展示了整个交互过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

流程图

在这里插入图片描述

TCP server 服务端

步骤如图所示
1 创建Socket 指定使用什么协议

 socket_fd = socket(AF_INET,SOCK_STREAM,0);

2 将Socket与地址和端口绑定

//set socket address
local_addr.sin_family = AF_INET;
local_addr.sin_port = htons(PORT);
local_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(local_addr.sin_zero),8);


//bind socket
ret = bind(socket_fd,(struct  sockaddr*)&local_addr,sizeof(struct sockaddr_in));

3 侦听端口(目前Socket和地址 端口绑定了 但是上层应用必须绑定对应的Socket)

ret = listen(socket_fd,backlog);

4 创建新的socket – 每次连接过来以后创建一个新的socket来收发数据 也就是accept socket (之前的socket 一直在侦听 请求连接是数据)

int addr_len = sizeof( struct sockaddr_in );
    //accept an new connection
    accept_fd = accept( socket_fd, (struct sockaddr *)&remote_addr, &addr_len );

5 recv接收数据

 ret = recv( accept_fd ,(void*)in_buf ,MESSAGE_SIZE ,0 );

6 send发送数据

send(accept_fd, (void*)in_buf, MESSAGE_SIZE, 0);

7 close关闭当前socket

 close(accept_fd);
 close(socket_fd);

服务端完整代码

//
// Created by zyc on 2022/5/5.
//


#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MESSAGE_SIZE 1024
#define PORT 8111
int main(){
    int ret = 0;

    int socket_fd = -1;
    int accept_fd = -1;

    int curpos = 0;
    int backlog = 10;
    int flag = 1;

    char in_buf[MESSAGE_SIZE] = {0,};

    struct sockaddr_in local_addr, remote_addr;

    //create a tcp socket
    socket_fd = socket(AF_INET,SOCK_STREAM,0);

    if (socket_fd==-1){
        perror("create socket error");
        exit(1);
    }

    //set option of socket
    ret = setsockopt(socket_fd,SOL_SOCKET,SO_REUSEADDR,
                     &flag,sizeof(flag));
    if ( ret == -1 ){
        perror("setsockopt error");
    }

    //set socket address
    local_addr.sin_family = AF_INET;
    local_addr.sin_port = htons(PORT);
    local_addr.sin_addr.s_addr = INADDR_ANY;
    bzero(&(local_addr.sin_zero),8);


    //bind socket
    ret = bind(socket_fd,(struct  sockaddr*)&local_addr,sizeof(struct sockaddr_in));
    if(ret == -1 ) {
        perror("bind error");
        exit(1);
    }

    ret = listen(socket_fd,backlog);
    if ( ret == -1 ){
        perror("listen error");
        exit(1);
    }

    //loop
    for(;;){
        int addr_len = sizeof( struct sockaddr_in );
        //accept an new connection
        accept_fd = accept( socket_fd, (struct sockaddr *)&remote_addr, &addr_len );
        for(;;){
            memset(in_buf, 0, MESSAGE_SIZE);

            //receive network data and print it
            ret = recv( accept_fd ,(void*)in_buf ,MESSAGE_SIZE ,0 );
            if(ret == 0 ){
                break;
            }
            printf( "receive message:%s\n", in_buf );
            send(accept_fd, (void*)in_buf, MESSAGE_SIZE, 0);
        }
        printf("close client connection...\n");
        close(accept_fd);
    }

    printf("quit server...\n");
    close(socket_fd);

    return 0;
}


TCP 客户端

在这里插入图片描述

客户端 类型 但是少了 绑定和侦听
因为在Connect阶段系统会默认分配

但是需要提前输入服务端的地址 代码如下

serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(SERVER_PORT);

//inet_addr()函数,将点分十进制IP转换成网络字节序IP

serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");

if(connect(socket_fd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0)
{
    perror("connect");
    return 1;
}
printf("success to connect server...\n");

客户端完整代码

//
// Created by zyc on 2022/5/5.
//

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

#include <fcntl.h>
#include <errno.h>
#include <netdb.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define SERVER_PORT 8111
#define MESSAGE_LENGTH 1024

int main(){
    int ret = -1;
    int socket_fd;

    //server addr
    struct sockaddr_in serverAddr;

    char sendbuf[MESSAGE_LENGTH];
    char recvbuf[MESSAGE_LENGTH];

    int data_len;

    if((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("socket");
        return 1;
    }

    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(SERVER_PORT);

    //inet_addr()函数,将点分十进制IP转换成网络字节序IP
//    serverAddr.sin_addr.s_addr = inet_addr("39.105.185.198");
    serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");

    if(connect(socket_fd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0)
    {
        perror("connect");
        return 1;
    }
    printf("success to connect server...\n");

    while(1)
    {
        memset(sendbuf, 0, MESSAGE_LENGTH);

        printf("<<<<send message:");

        gets(sendbuf);
        //printf("\n");
        ret = send(socket_fd, sendbuf, strlen(sendbuf), 0);
        if(ret <= 0 ){
            printf("the connection is disconnection!\n");
            break;
        }

        if(strcmp(sendbuf, "quit") == 0){
            break;
        }

        printf(">>> echo message:");

        recvbuf[0] = '\0';
        data_len = recv(socket_fd, recvbuf, MESSAGE_LENGTH, 0);

        recvbuf[data_len] = '\0';

        printf("%s\n", recvbuf);

    }

    close(socket_fd);

    return 0;

}





HP-Socket 是一套通用的高性能 TCP/UDP/HTTP 通信框架,包含服务端组件、客户端组件和Agent组件,广泛适用于各种不同应用场景的 TCP/UDP/HTTP 通信系统,提供 C/C++、C#、Delphi、E(易语言)、Java、Python 等编程语言接口。HP-Socket 对通信层实现完全封装,应用程序不必关注通信层的任何细节;HP-Socket 提供基于事件通知模型的 API 接口,能非常简单高效地整合到新旧应用程序中。    为了让使用者能方便快速地学习和使用 HP-Socket ,迅速掌握框架的设计思想和使用方法,特此精心制作了大量 Demo 示例(如:PUSH 模型示例、PULL 模型示例、PACK 模型示例、性能测试示例以及其它编程语言示例)。HP-Socket 目前运行在 Windows 平台,将来会实现跨平台支持。 [15:47 2018/11/05] 同步更新到5.4.2正式版 [10:37 2018/10/23] 1、英文模块IHttpSyncClient组件大改 2、IWinHttp组件添加若干命令(PS:忘记是哪些了。。。) 3、升级到5.4.2 rc3 版本 4、增加client同步例子 [10:30 2018/9/25] v5.4.2 更新: > SSL 组件更新: ----------------- 1、SSL 组件可以手工启动 SSL 握手,从而可以对 SSL/Https 通信执行代理服务器设置等前置操作 2、SSL 组件(Server/Agent/Client)增加以下接口方法支持手工启动 SSL 握手 1) StartSSLHandShake():手工启动 SSL 握手,当通信组件设置为非自动握手时,需要调用本方法启动 SSL 握手 2) SetSSLAutoHandShake():设置通信组件握手方式(默认:TRUE,自动握手) 3) IsSSLAutoHandShake():获取通信组件握手方式 > 其他功能更新: ----------------- 1、所有可能导致 Socket 关闭的组件接口方法都在 Socket 通信线程中异步触发 OnClose 事件 2、Server 与 Agent 组件的 DIRECT 发送策略也支持通过 GetPendingDataLength() 方法实现流控 3、Server 与 Agent 组件的 Disconnect() 方法不再支持‘非强制断开’(仍然保留bForce 参数),调用时都会强制断开 4、OnSend 事件支持 三种同步策略 1) OSSP_NONE:不同步(默认) 1) OSSP_CLOSE:同步 OnClose 1) OSSP_RECEIVE:同步 OnClose 和 OnReceive(只用于 TCP 组件) > 升级说明: ----------------- 1、HP-Socket v5.4.2 完全兼容 HP-Socket v5.4.1 版本,可以直接替换升级 [18:41 2018/8/27] 1、修复英文模块submit_task最后一个参数错误问题,莫名其妙变成了字节集 [11:04 2018/8/27] 1、更新hpsocket为 beta11 2、submit_task 提交的任务不用去管回调里面的ptask参数。内部自动处理。 [16:57 2018/8/24] 1、修复中文模块部分命令错误问题 2、修复英文模块几处命令错误问题 3、增加websocket例程,本来httpclient里面人,有些人就是装看不见。 4、更新hpsocket为 beta9 [12:57 2018/8/15] 1、修复模块汇编的bug,原因是取消了ww汇编库 [11:55 2018/8/15] 1、模块更新为beta8 2、新增api: HP_Agent_IsConnected  -->  Agent.IsConnected() HP_Client_IsConnected  -->  Client.IsConnected() HP_Server_IsConnected  -->  Server.IsConnected() [9:18 2018/8/6] 1、性能优化 2、由于某些人吐槽中文版模块吐槽的厉害,遂决定不再更新中文版。 3、\demo\old 目录下放的是以前旧的例程源码,并不再更新 [12:57 2018/8/1] 修改模块IBufferPtr类,具体调用方式查看 TestEcho-New-Agent.e TestEcho-New-Server.e TestEcho-Http-Serve.e TestEcho-Http-Serve-bigfile.e  改名为 TestEcho-Ht
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值