Linux网络编程(TCP)

本文详细探讨了Linux环境下的TCP网络编程,包括服务端和客户端的示例代码,以及服务端的select和epoll模型。同时,对比了select、poll和epoll在处理大量并发连接时的性能和效率差异,强调了epoll在高并发场景下的优势,如无句柄数量限制和使用回调函数减少系统调用开销。
摘要由CSDN通过智能技术生成

TCP

service.c
服务端

#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int main(void)
{
    int sfp,nfp;
    struct sockaddr_in s_add,c_add;
    int sin_size;
    unsigned short portnum=0x8888;
    char buff[100]={0};

    printf("Hello,welcome to my server !\r\n");
    sfp = socket(AF_INET, SOCK_STREAM, 0);
    if(-1 == sfp)
    {
        printf("socket fail ! \r\n");
        return -1;
    }
    printf("socket ok !\r\n");

    bzero(&s_add,sizeof(struct sockaddr_in));
    s_add.sin_family=AF_INET;
    s_add.sin_addr.s_addr=htonl(INADDR_ANY);
    s_add.sin_port=htons(portnum);

    if(-1 == bind(sfp,(struct sockaddr *)(&s_add), sizeof(struct sockaddr)))
    {
        printf("bind fail !\r\n");
        return -1;
    }
    printf("bind ok !\r\n");

    if(-1 == listen(sfp,5))
    {
        printf("listen fail !\r\n");
        return -1;
    }
    printf("listen ok\r\n");
    while(1)
    {
        sin_size = sizeof(struct sockaddr_in);

        nfp = accept(sfp, (struct sockaddr *)(&c_add), &sin_size);
        if(-1 == nfp)
        {
            printf("accept fail !\r\n");
            return -1;
        }
        read(nfp,buff,100);
        printf("received:%s\n", buff);

        if(-1 == write(nfp,buff,strlen(buff)+1))
        {
            printf("write fail!\r\n");
            return -1;
        }
        printf("write ok!\r\n");
        close(nfp);
    }
    close(sfp);
    return 0;
}

makefile:

server:server.o
    gcc -o server server.o
server.o:server.c
    gcc -c server.c -o server.o
clean:
    rm -f *.o server

=====================
客户端
client.c

#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>

int main(void)
{
    int cfd;
    int recbytes;
    int sin_size;
    char buffer[1024]={0};   
    struct sockaddr_in s_add,c_add;
    unsigned short portnum=0x8888; 
    printf("Hello,welcome to client !\r\n");

    cfd = socket(AF_INET, SOCK_STREAM, 0);
    if(-1 == cfd)
    {
        printf("socket fail ! \r\n");
        return -1;
    }
    printf("socket ok !\r\n");

    bzero(&s_add,sizeof(struct sockaddr_in));
    s_add.sin_family=AF_INET;
    s_add.sin_addr.s_addr= inet_addr("127.0.0.1");
    s_add.sin_port=htons(portnum);
    printf("s_addr = %#x ,port : %#x\r\n",s_add.sin_addr.s_addr,s_add.sin_port);

    if(-1 == connect(cfd,(struct sockaddr *)(&s_add), sizeof(struct sockaddr)))
    {
        printf("connect fail !\r\n");
        return -1;
    }
    printf("connect ok !\r\n");
    write(cfd,"hello tcp socket", strlen("hello tcp socket")+1);

    if(-1 == (recbytes = read(cfd,buffer,1024)))
    {
        printf("read data fail !\r\n");
        return -1;
    }
    printf("read ok\r\nREC:\r\n");
    buffer[recbytes]='\0';
    printf("%s\r\n",buffer);
    getchar();
    close(cfd);
    return 0;
}

makefile:

client:client.o
    gcc -o client client.o
client.o:client.c
    gcc -c client.c -o client.o
clean:
    rm -f *.o client

UDP

a端
a.c

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

#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>

int port=6789;
int main(int argc, char** argv) 
{
    int fd; //套接口描述字
    int i=0;
    char buf[80];
    struct sockaddr_in address;//处理网络通信的地址

    bzero(&address,sizeof(address));
    address.sin_family=AF_INET;
    address.sin_addr.s_addr=inet_addr("127.0.0.1");//这里不一样
    address.sin_port=htons(port);

    //创建一个 UDP socket

    fd=socket(AF_INET,SOCK_DGRAM,0);//IPV4 SOCK_DGRAM 数据报套接字(UDP协议)

    for(i=0;i<20;i++)
    {
        /*
        * sprintf(s, "%8d%8d", 123, 4567); //产生:" 123 4567" 
        * 将格式化后到 字符串存放到s当中
        */
        sprintf(buf,"hello udp socket %d",i);

        /*int PASCAL FAR sendto( SOCKET s, const char FAR* buf, int len, int flags,const struct sockaddr FAR* to, int tolen);  
        * s:一个标识套接口的描述字。 
        * buf:包含待发送数据的缓冲区。  
        * len:buf缓冲区中数据的长度。 
        * flags:调用方式标志位。  
        * to:(可选)指针,指向目的套接口的地址。 
        * tolen:to所指地址的长度。 
           */
        s
Linux网络编程中,TCP是一种可靠的传输协议,用于在网络上建立可靠的连接。TCP连接具有以下特点和问题: 1. TCP连接不能同时打开多次,当一个TCP连接处于TIME_WAIT状态时,无法立即使用该连接占用的端口来建立新的连接。如果需要强制立即使用处于TIME_WAIT状态的连接所占用的端口,可以通过setsockopt()方法设置socket选项SO_REUSEADDR来实现。 2. TCP是面向字节流的协议,发送端执行的写操作次数和接收端执行的读操作次数之间没有数量关系。这可能导致粘包问题,即发送端多次发送的数据在接收端一次性收取完成,无法准确区分出数据的边界。为了解决粘包问题,可以采用以下方法: - 发送端每次发送数据后等待接收端的回复再进行下一次发送。 - 定义协议,通过在数据中添加特定的标识来区分数据的边界,例如使用【长】【宽】【高】表示长度、宽度和高度。 3. TIME_WAIT状态存在的意义主要有两个: - 可靠地终止TCP连接,确保双方都已经完全接收了对方的所有数据。 - 确保迟到的TCP报文有足够的时间被识别并丢弃,特别是在服务器主动关闭连接时。 总结起来,在Linux网络编程中,TCP作为一种可靠的传输协议,需要注意处理TIME_WAIT状态和粘包问题。可以通过设置socket选项和制定协议来解决这些问题,以保证网络连接的可靠性和数据的准确传输。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Linux网络编程 | TCP详解](https://blog.csdn.net/weixin_52983138/article/details/125077602)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值