Linux网络编程——TCP和UDP通信

  • TCP协议流程图、TCP建立即时聊天
  • TCP即时聊天升级:服务器在客户端断开后不断开,客户端可以多次重连服务器进行即时聊天
  • UDP协议流程图、UDP建立即时连接
  • 如果在已经处于 ESTABLISHED状态下的socket(一般由端口号和标志符区分)需调用closesocket(一般不会立即关闭而经历TIME_WAIT的过程)后想继续重用该socket,但也可以直接用setsockopt和reuse。
  • SO_RCVLOWAT设置接收缓冲区下限

1、TCP协议的流程图

服务端:socket---bind---listen---while(1){---accept---recv---send---close---}---close
客户端:socket----------------------------------connect---send---recv-----------------close

TCP建立即时聊天

tcp_client.c

#include <func.h>

int main(int argc,char* argv[])
{
    ARGS_CHECK(argc,3);
    int socketFd;
    socketFd=socket(AF_INET,SOCK_STREAM,0);
    ERROR_CHECK(socketFd,-1,"socket");
    struct sockaddr_in ser;
    bzero(&ser,sizeof(ser));
    ser.sin_family=AF_INET;
    ser.sin_port=htons(atoi(argv[2]));
    ser.sin_addr.s_addr=inet_addr(argv[1]);//点分十进制转为32位的网络字节序
    int ret;
    ret=connect(socketFd,(struct sockaddr*)&ser,sizeof(ser));
    ERROR_CHECK(ret, -1, "connect");
    printf("connect success\n");
    char buf[128]={0};
    fd_set rdset;
    while(1){
        FD_ZERO(&rdset);
        FD_SET(STDIN_FILENO, &rdset);
        FD_SET(socketFd, &rdset);
        ret = select(socketFd + 1, &rdset, NULL, NULL, NULL);
        if(FD_ISSET(socketFd, &rdset)){
            bzero(buf, sizeof(buf));
            ret = recv(socketFd, buf, sizeof(buf), 0);
            ERROR_CHECK(ret, -1, "recv");
            if(ret == 0){
                printf("byebye!\n");
                break;
            }
            printf("%s\n", buf);
        }
        if(FD_ISSET(STDIN_FILENO, &rdset)){
            memset(buf, 0, sizeof(buf));
            ret = read(STDIN_FILENO, buf, sizeof(buf));
            if(ret == 0){
                printf("byebye!\n");
                break;
            }
            ret = send(socketFd, buf ,strlen(buf) - 1, 0);
            ERROR_CHECK(ret, -1, "send");
        }
    }
    close(socketFd);
}

tcp_server.c

#include <func.h>

int main(int argc,char* argv[])
{
    ARGS_CHECK(argc,3);
    int socketFd;
    socketFd = socket(AF_INET,SOCK_STREAM,0);
    ERROR_CHECK(socketFd, -1, "socket");
    struct sockaddr_in ser;
    bzero(&ser, sizeof(ser));
    ser.sin_family = AF_INET;
    ser.sin_port = htons(atoi(argv[2]));
    ser.sin_addr.s_addr = inet_addr(argv[1]);//点分十进制转为32位的网络字节序
    int ret;
    ret = bind(socketFd, (struct sockaddr*)&ser, sizeof(ser));
    ERROR_CHECK(ret, -1, "bind");
    listen(socketFd, 10);//缓冲区的大小,一瞬间能够放入的客户端连接信息
    int new_fd;
    struct sockaddr_in client;
    bzero(&client, sizeof(client));
    int addrlen = sizeof(client);
    new_fd = accept(socketFd, (struct sockaddr*)&client, &addrlen);
    ERROR_CHECK(new_fd, -1, "accept");
    printf("client ip=%s, port=%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
    fd_set rdset;
    char buf[128] = {0};
    while(1){
        FD_ZERO(&rdset);
        FD_SET(STDIN_FILENO, &rdset);
        FD_SET(new_fd, &rdset);
        ret = select(new_fd + 1, &rdset, NULL, NULL, NULL);
        if(FD_ISSET(new_fd, &rdset)){
            bzero(buf, sizeof(buf));
            ret = recv(new_fd, buf, sizeof(buf), 0);
            ERROR_CHECK(ret, -1, "recv");
            if(ret == 0){
                printf("byebye!\n");
                break;
            }
            printf("%s\n", buf);
        }
        if(FD_ISSET(STDIN_FILENO, &rdset)){
            memset(buf, 0, sizeof(buf));
            ret = read(STDIN_FILENO, buf, sizeof(buf));
            if(ret == 0){
                printf("byebye!\n");
                break;
            }
            ret = send(new_fd, buf, strlen(buf) - 1, 0);
            ERROR_CHECK(ret, -1, "send");
        }
    }
    close(new_fd);
    close(socketFd);
    return 0;
}

2、TCP即时聊天升级:服务器在客户端断开后不断开,客户端可以多次重连服务器进行即时聊天

tcp_server.c

#include <func.h>

int main(int argc,char* argv[])
{
    ARGS_CHECK(argc,3);
    int socketFd;
    socketFd = socket(AF_INET,SOCK_STREAM,0);
    ERROR_CHECK(socketFd, -1, "socket");
    struct sockaddr_in ser;
    bzero(&ser, sizeof(ser));
    ser.sin_family = AF_INET;
    ser.sin_port = htons(atoi(argv[2]));
    ser.sin_addr.s_addr = inet_addr(argv[1]);//点分十进制转为32位的网络字节序
    int ret;
    ret = bind(socketFd, (struct sockaddr*)&ser, sizeof(ser));
    ERROR_CHECK(ret, -1, "bind");
    listen(socketFd, 10);//缓冲区的大小,一瞬间能够放入的客户端连接信息
    int new_fd;
    struct sockaddr_in client;
    bzero(&client, sizeof(client));
    int addrlen = sizeof(client);
    char buf[128] = {0};
    fd_set rdset;
    fd_set needMonitorSet; //需要监听的描述符集合
    FD_ZERO(&needMonitorSet);
    FD_SET(STDIN_FILENO, &needMonitorSet);
    FD_SET(socketFd, &needMonitorSet);
    while(1){
        memcpy(&rdset, &needMonitorSet, sizeof(fd_set));
        ret = select(11, &rdset, NULL, NULL, NULL); //设最大监控描述符为10
        if(FD_ISSET(socketFd, &rdset)){ //如果监听到客户端则accept接受远程计算机的连接请求
            new_fd = accept(socketFd, (struct sockaddr*)&client, &addrlen); //accept函数接受一个连接时,会返回一个新的socket标识符,以后数据的数据传输和读取就要通过这个新的socket编号来处理,原来的socket继续监听其他客户机的连接请求。
            ERROR_CHECK(new_fd, -1, "accept");
            printf("client ip=%s, port=%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
            FD_SET(new_fd, &needMonitorSet);
        }
        if(FD_ISSET(new_fd, &rdset)){
            bzero(buf, sizeof(buf));
            ret = recv(new_fd, buf, sizeof(buf), 0);
            ERROR_CHECK(ret, -1, "recv");
            if(ret == 0){
                printf("byebye!\n");
                FD_CLR(new_fd, &needMonitorSet);  //从needMonitorSet中删除new_fd
                close(new_fd);
                continue;
            }
            printf("%s\n", buf);
        }
        if(FD_ISSET(STDIN_FILENO, &rdset)){
            memset(buf, 0, sizeof(buf));
            ret = read(STDIN_FILENO, buf, sizeof(buf));
            if(ret == 0){
                printf("byebye!\n");
                break;
            }
            ret = send(new_fd, buf, strlen(buf) - 1, 0);
            ERROR_CHECK(ret, -1, "send");
        }
    }
    close(socketFd);
    return 0;
}

tcp_client.c和1同

3、使用UDP协议的流程图

服务端:socket---bind---recvfrom---sendto---close
客户端:socket----------sendto---recvfrom---close

  • sendto()函数原型:
    int sendto(int sockfd, const void msg,int len,unsigned int flags,const struct sockaddr to, int tolen);

    该函数比send()函数多了两个参数,to表示目地机的IP地址和端口号信息,而tolen常常被赋值为sizeof (struct sockaddr)。sendto 函数也返回实际发送的数据字节长度或在出现发送错误时返回-1。

  • recvfrom()函数原型:

    **int recvfrom(int sockfd,void buf,int len,unsigned int flags,struct sockaddr from,int *fromlen);**
    from是一个struct sockaddr类型的变量,该变量保存连接机的IP地址及端口号。fromlen常置为sizeof (struct sockaddr)。当recvfrom()返回时,fromlen包含实际存入from中的数据字节数。Recvfrom()函数返回接收到的字节数或当出现错误时返回-1,并置相应的errno。

    UDP传输一个数据报示例:

    udp_server.c

#include <func.h>

int main(int argc, char **argv){
    ARGS_CHECK(argc, 3);
    int socketFd;
    socketFd = socket(AF_INET, SOCK_DGRAM, 0);
    ERROR_CHECK(socketFd, -1, "socket");
    struct sockaddr_in ser;
    bzero(&ser,sizeof(ser));
    ser.sin_family = AF_INET;
    ser.sin_port = htons(atoi(argv[2]));
    ser.sin_addr.s_addr = inet_addr(argv[1]);//点分十进制转为32位的网络字节序
    int ret;
    ret = bind(socketFd, (struct sockaddr*)&ser, sizeof(ser));
    ERROR_CHECK(ret, -1, "bind");
    char buf[128] = {0};
    struct sockaddr_in client;
    int addrlen = sizeof(client);
    ret = recvfrom(socketFd, buf, 5, 0, (struct sockaddr*)&client, &addrlen);
    ERROR_CHECK(ret, -1, "recvfrom");
    printf("client ip = %s, port = %d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
    printf("udp server gets %s\n", buf);
    //bzero(buf, sizeof(buf));
    //ret = recvfrom(socketFd, buf, 5, 0, (struct sockaddr*)&client, &addrlen);
    //ERROR_CHECK(ret, -1, "recvfrom");
    //printf("udp server gets %s\n", buf);
    ret = sendto(socketFd, "world", 5, 0, (struct sockaddr*)&client, sizeof(client));
    ERROR_CHECK(ret, -1, "sendto");
    close(socketFd);
    return 0;
}

udp_client.c

#include <func.h>

int main(int argc, char *argv[]){
    ARGS_CHECK(argc, 3);
    int socketFd;
    socketFd = socket(AF_INET, SOCK_DGRAM, 0);
    ERROR_CHECK(socketFd, -1, "socket");
    struct sockaddr_in ser;
    bzero(&ser, sizeof(ser));
    ser.sin_family = AF_INET;
    ser.sin_port = htons(atoi(argv[2]));
    ser.sin_addr.s_addr = inet_addr(argv[1]);
    int ret;
    ret = sendto(socketFd, "helloworld", 10, 0, (struct sockaddr*)&ser, sizeof(ser));
    ERROR_CHECK(ret, -1, "sendto");
    char buf[128] = {0};
    ret = recvfrom(socketFd, buf, sizeof(buf), 0, NULL, NULL);
    ERROR_CHECK(ret, -1, "recvfrom");
    printf("udp client gets %s\n", buf);
    close(socketFd);
    return 0;
}

4、使用UDP协议建立即时连接

udp_server.c

#include <func.h>

int main(int argc, char **argv){
    ARGS_CHECK(argc, 3);
    int socketFd;
    socketFd = socket(AF_INET, SOCK_DGRAM, 0);
    ERROR_CHECK(socketFd, -1, "socket");
    struct sockaddr_in ser;
    bzero(&ser,sizeof(ser));
    ser.sin_family = AF_INET;
    ser.sin_port = htons(atoi(argv[2]));
    ser.sin_addr.s_addr = inet_addr(argv[1]);//点分十进制转为32位的网络字节序
    int ret;
    ret = bind(socketFd, (struct sockaddr*)&ser, sizeof(ser));
    ERROR_CHECK(ret, -1, "bind");
    char buf[128] = {0};
    struct sockaddr_in client;
    int addrlen = sizeof(client);
    printf("client ip = %s, port = %d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
    fd_set rdset;
    while(1){
        FD_ZERO(&rdset);
        FD_SET(STDIN_FILENO, &rdset);
        FD_SET(socketFd, &rdset);
        ret = select(socketFd + 1, &rdset, NULL, NULL, NULL);
        if(FD_ISSET(socketFd, &rdset)){
            bzero(buf, sizeof(buf));
            ret = recvfrom(socketFd, buf, sizeof(buf), 0, (struct sockaddr*)&client, &addrlen);
            ERROR_CHECK(ret, -1, "recvfrom");
            printf("%s\n", buf);
        }
        if(FD_ISSET(STDIN_FILENO, &rdset)){
            bzero(buf, sizeof(buf));
            ret = read(STDIN_FILENO, buf, sizeof(buf));
            if(0 == ret){
                printf("byeybye\n");
                break;
            }
            ret = sendto(socketFd, buf, strlen(buf) - 1, 0, (struct sockaddr*)&client, sizeof(client));
            ERROR_CHECK(ret, -1, "sendto");
        }
    }
    close(socketFd);
    return 0;
}

udp_client.c

#include <func.h>

int main(int argc, char *argv[]){
    ARGS_CHECK(argc, 3);
    int socketFd;
    socketFd = socket(AF_INET, SOCK_DGRAM, 0);
    ERROR_CHECK(socketFd, -1, "socket");
    struct sockaddr_in ser;
    bzero(&ser, sizeof(ser));
    ser.sin_family = AF_INET;
    ser.sin_port = htons(atoi(argv[2]));
    ser.sin_addr.s_addr = inet_addr(argv[1]);
    int ret;
    char buf[128] = {0};
    fd_set rdset;
    while(1){
        FD_ZERO(&rdset);
        FD_SET(STDIN_FILENO, &rdset);
        FD_SET(socketFd, &rdset);
        ret = select(socketFd + 1, &rdset, NULL, NULL, NULL);
        if(FD_ISSET(socketFd, &rdset)){
            bzero(buf, sizeof(buf));
            ret = recvfrom(socketFd, buf, sizeof(buf), 0, NULL, NULL);
            ERROR_CHECK(ret, -1, "recvfrom");
            printf("%s\n", buf);
        }
        if(FD_ISSET(STDIN_FILENO, &rdset)){
            bzero(buf, sizeof(buf));
            ret = read(STDIN_FILENO, buf, sizeof(buf));
            if(0 == ret){
                printf("byeybye\n");
                break;
            }
            ret = sendto(socketFd, buf, strlen(buf) - 1, 0, (struct sockaddr*)&ser, sizeof(ser));
            ERROR_CHECK(ret, -1, "sendto");
        }
    }
    close(socketFd);
    return 0;
}

5、如果在已经处于 ESTABLISHED状态下的socket(一般由端口号和标志符区分)需调用closesocket(一般不会立即关闭而经历TIME_WAIT的过程)后想继续重用该socket,但也可以直接用setsockopt和reuse。

int reuse=1;
setsockopt(s,SOL_SOCKET ,SO_REUSEADDR,(const char*)&reuse,sizeof(int));

tcp_server.c

#include <func.h>

int main(int argc,char* argv[])
{
    ARGS_CHECK(argc,3);
    int socketFd;
    socketFd = socket(AF_INET,SOCK_STREAM,0);
    ERROR_CHECK(socketFd, -1, "socket");
    int ret;
    int reuse = 1;
    ret = setsockopt(socketFd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int));
    ERROR_CHECK(ret, -1, "setsockopt");
    struct sockaddr_in ser;
    bzero(&ser, sizeof(ser));
    ser.sin_family = AF_INET;
    ser.sin_port = htons(atoi(argv[2]));
    ser.sin_addr.s_addr = inet_addr(argv[1]);//点分十进制转为32位的网络字节序
    ret = bind(socketFd, (struct sockaddr*)&ser, sizeof(ser));
    ERROR_CHECK(ret, -1, "bind");
    listen(socketFd, 10);//缓冲区的大小,一瞬间能够放入的客户端连接信息
    int new_fd;
    struct sockaddr_in client;
    bzero(&client, sizeof(client));
    int addrlen = sizeof(client);
    new_fd = accept(socketFd, (struct sockaddr*)&client, &addrlen);
    ERROR_CHECK(new_fd, -1, "accept");
    printf("client ip=%s, port=%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
    fd_set rdset;
    char buf[128] = {0};
    while(1){
        FD_ZERO(&rdset);
        FD_SET(STDIN_FILENO, &rdset);
        FD_SET(new_fd, &rdset);
        ret = select(new_fd + 1, &rdset, NULL, NULL, NULL);
        if(FD_ISSET(new_fd, &rdset)){
            bzero(buf, sizeof(buf));
            ret = recv(new_fd, buf, sizeof(buf), 0);
            ERROR_CHECK(ret, -1, "recv");
            if(ret == 0){
                printf("byebye!\n");
                break;
            }
            printf("%s\n", buf);
        }
        if(FD_ISSET(STDIN_FILENO, &rdset)){
            memset(buf, 0, sizeof(buf));
            ret = read(STDIN_FILENO, buf, sizeof(buf));
            if(ret == 0){
                printf("byebye!\n");
                break;
            }
            ret = send(new_fd, buf, strlen(buf) - 1, 0);
            ERROR_CHECK(ret, -1, "send");
        }
    }
    close(new_fd);
    close(socketFd);
    return 0;
}

tcp_client.c和1同

6、SO_RCVLOWAT:接收缓冲区下限

tcp_server_rcvlowat.c

#include <func.h>

int main(int argc,char* argv[])
{
    ARGS_CHECK(argc,3);
    int socketFd;
    socketFd = socket(AF_INET,SOCK_STREAM,0);
    ERROR_CHECK(socketFd, -1, "socket");
    int ret;
    int reuse = 1;
    ret = setsockopt(socketFd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int));
    ERROR_CHECK(ret, -1, "setsockopt");
    struct sockaddr_in ser;
    bzero(&ser, sizeof(ser));
    ser.sin_family = AF_INET;
    ser.sin_port = htons(atoi(argv[2]));
    ser.sin_addr.s_addr = inet_addr(argv[1]);//点分十进制转为32位的网络字节序
    ret = bind(socketFd, (struct sockaddr*)&ser, sizeof(ser));
    ERROR_CHECK(ret, -1, "bind");
    listen(socketFd, 10);//缓冲区的大小,一瞬间能够放入的客户端连接信息
    int new_fd;
    struct sockaddr_in client;
    bzero(&client, sizeof(client));
    int addrlen = sizeof(client);
    new_fd = accept(socketFd, (struct sockaddr*)&client, &addrlen);
    ERROR_CHECK(new_fd, -1, "accept");
    printf("client ip=%s, port=%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
    fd_set rdset;
    char buf[128] = {0};
    int rcvLowAt = 10;
    ret=setsockopt(new_fd,SOL_SOCKET,SO_RCVLOWAT,&rcvLowAt,sizeof(int));

    ERROR_CHECK(ret, -1, "setsockopt");
    while(1){
        FD_ZERO(&rdset);
        FD_SET(STDIN_FILENO, &rdset);
        FD_SET(new_fd, &rdset);
        ret = select(new_fd + 1, &rdset, NULL, NULL, NULL);
        if(FD_ISSET(new_fd, &rdset)){
            bzero(buf, sizeof(buf));
            ret = recv(new_fd, buf, sizeof(buf), 0);
            ERROR_CHECK(ret, -1, "recv");
            if(ret == 0){
                printf("byebye!\n");
                break;
            }
            printf("%s\n", buf);
        }
        if(FD_ISSET(STDIN_FILENO, &rdset)){
            memset(buf, 0, sizeof(buf));
            ret = read(STDIN_FILENO, buf, sizeof(buf));
            if(ret == 0){
                printf("byebye!\n");
                break;
            }
            ret = send(new_fd, buf, strlen(buf) - 1, 0);
            ERROR_CHECK(ret, -1, "send");
        }
    }
    close(new_fd);
    close(socketFd);
    return 0;
}

tcp_client.c和1同

原文地址:https://www.cnblogs.com/Mered1th/p/10803634.html

时间: 2024-08-26 16:36:46

Linux网络编程——TCP和UDP通信的相关文章

Linux 网络编程——TCP 和 UDP 数据报格式详解

TCP 报文格式 TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的.可靠的.基于字节流的传输层通信协议. TCP 报文段的报头有 10 个必需的字段和 1 个可选字段.报头至少为 20 字节.报头后面的数据是可选项. 1)源端口(16位) 标识发送报文的计算机端口或进程.一个 TCP 报文段必须包括源端口号,使目的主机知道应该向何处发送确认报文. 2)目的端口(16位) 标识接收报文的目的主机的端口或进程. 3) 序号(也叫序列号)(32位) 用

Linux网络编程-----TCP程序设计

基于TCP-服务器 1.创建一个socket, 2.绑定IP地址.端口等信息到socket上,用函数bind() 3.设置允许的最大连接数,用函数listen(). 4.等待来自客户端的连接请求,用accept() 5.收发数据,用函数send()和recv(),或者read()和write() 6.关闭网络连接 基于TCP-客户端 1.socket创建套接字 2.设置要连接服务器的IP地址和端口等属性 3.连接服务器,用函数connect() 4.收发数据,用函数send()和recv(),或

Linux网络编程10&mdash;&mdash;使用UDP实现五子棋对战

思路 1. 通信 为了同步双方的棋盘,每当一方在棋盘上落子之后,都需要发送给对方一个msg消息,让对方知道落子位置.msg结构体如下: /* 用于发给对方的信息 */ typedef struct tag_msg { int msg_type; /* 悔棋? */ int msg_color; int msg_row; int msg_col; }MSG, *pMSG; 2. 悔棋 用链表头插法来模拟栈,链表记录了双方下子的轨迹.结构如下: /* 记录每一步的轨迹 */ typedef stru

Socket网络编程TCP、UDP示例

Socket网络编程: 1) OSI(了解): 国际标准化组织ISO(International Orgnization for Standardization)指定了网络通信的模型:开放系统互联(OSI,Open System Interconnection),把网络通信工作分为七层:物理层(最底层)-数据链路层-网络层-传输层-会话层-表示层-应用层(应用程序) 数据格式 功能与连接方式 典型设备 应用层 网络服务与使用者应用程序间的一个接口 表示层 数据表示.数据安全.数据压缩 会话层 建

Socket网络编程TCP、UDP演示样例

Socket网络编程: 1) OSI(了解): 国际标准化组织ISO(International Orgnization for Standardization)指定了网络通信的模型:开放系统互联(OSI,Open System Interconnection),把网络通信工作分为七层:物理层(最底层)-数据链路层-网络层-传输层-会话层-表示层-应用层(应用程序) 数据格式 功能与连接方式 典型设备 应用层 网络服务与使用者应用程序间的一个接口 表示层 数据表示.数据安全.数据压缩 会话层 建

Linux网络编程——tcp并发服务器(poll实现)

想详细彻底地了解poll或看懂下面的代码请参考<Linux网络编程--I/O复用之poll函数> 代码: #include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/select.h> #include <sys/time.h> #include <sys/socket.h> #incl

[网络编程] TCP、UDP区别以及TCP传输原理、拥塞避免、连接建立、连接释放总结

TCP.UDP都是属于运输层的协议,提供端到端的进程之间的逻辑通信,而IP协议(网络层)是提供主机间的逻辑通信,应用层规定应用进程在通信时所遵循的协议.一.UDP主要特点:传输的是用户数据报协议.1.UDP是无连接的,即发送数据之前不需要建立连接.2.UDP 使用尽最大努力交付,即不保证可靠交付,同时也不使用拥塞控制.3.UDP是面向报文的.UDP没有拥塞控制,很适合多媒体通信的要求.4.UDP支持一对一.一对多.多对一和多对多的交互通信.5.UDP的首部开销小,只有 8个字节.发送方 UDP对

Linux 网络编程——TCP编程

概述 TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的.可靠的.基于字节流的传输层通信协议. TCP 具有以下特点: 1)电话系统服务模式的抽象 2)每一次完整的数据传输都要经过建立连接.使用连接.终止连接的过程 3)可靠.出错重传.且每收到一个数据都要给出相应的确认,保证数据传输的可靠性 TCP 编程的 C/S 架构 基于 TCP 的网络编程开发分为服务器端和客户端两部分,常见的核心步骤和流程如下: TCP 客户端编程 所需头文件:#inclu

linux网络编程--tcp/udp编程模型

tcp 模型如下: 上面的模型已经很清楚了 具体函数用法就不细说了 请看tcp简单的例子: 其中server.c #include <stdio.h>#include <string.h>#include <stdlib.h>#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include <arpa/inet.h> #define e