TCP协议的客户端和服务器端通信

客户端:向服务器发送连接请求给服务器发送数据,并且读取服务器端回写的数据。

tcp协议特点:面向连接 可靠的 流式服务 应答确认超时重传

客户端和服务器端的通信通过套接字socket实现,套接字是两台主机之间通信的端点。

客户端和服务器端的通信由以下函数实现:

服务器端:

socket创建套接字

bind() 绑定 服务端用于将把用于通信的地址和端口绑定到 [socket]上

listen() 监听 设置最大的可连接的线路的数量

accept ()是一个阻塞函数(注:执行一该函数,则连接一次)

send recv()收发消息

close关闭

客户端:

socket创建套接字

connect() 发出连接请求

send recv 收发消息

close 关闭请求

服务器端代码如下:

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

int main()
{
    int sockfd = socket(AF_INET,SOCK_STREAM,0);//创建监听套接字
    if ( sockfd == -1 )
    {
        exit(1);
    }

    struct sockaddr_in saddr,caddr;//tcp专用socket结构体
    memset(&saddr,0,sizeof(saddr));
    //初始化结构体
    saddr.sin_family = AF_INET;//设定使用ipv4协议
    saddr.sin_port = htons(6000);//端口号   1024知名端口   4096保留的端口  大于4096 临时端口  3306mysql端口号
    saddr.sin_addr.s_addr = inet_addr("127.0.0.1");//服务器端地址

    int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));//给套接字绑定端口号和地址  第二个参数需要把专用的强转为通用的
    if ( res == -1 )
    {
        printf("bind err
");
        close(sockfd);
        exit(1);
    }

    res = listen(sockfd,5);//设置监听队列
    if ( res == -1 )
    {
        close(sockfd);
        exit(1);
    }

    while( 1 )
    {
        int len = sizeof(caddr);
        int c = accept(sockfd,(struct sockaddr*)&caddr,&len);//阻塞  c链接套接字   会有很多个c产生  只要有一个客户端连接上了就会产生一个c  accept是唯一来判断客户端是否关闭的标志
        if ( c == -1 )
        {
            continue;
        }
        printf("accept:%d
", c);
        while(1)
        {
        char buff[128] = {0};
        int n = recv(c,buff,127,0);//阻塞
        if (n <= 0)//  客户端关闭时recv会发生阻塞  返回n=0 则退出这个循环 服务器端会关闭
        {
            break;
        }
        printf("recv(%d):%s
",c,buff);
        send(c,"ok",2,0);
        close(c);//客户端关闭时  停止收发 退出循环 服务器返回 accept处重新链接客户端
        }
}

客户端代码如下:

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

int main()
{
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    if ( sockfd == -1 )
    {
        exit(1);
    }

    struct sockaddr_in saddr;
    memset(&saddr,0,sizeof(saddr));
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(6000);//htons主机转网络字节号 防止大小端
    saddr.sin_addr.s_addr = inet_addr("127.0.0.1");

    int res = connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));//进行三次握手  
    if ( res == -1 )
    {
        printf("connect failed
");
        close(sockfd);
        exit(1);
    }
    while (1) {
        printf("input
");
        char buff[128] = { 0 };
        fgets(buff, 128, stdin);
        if (strncmp(buff, "end", 3) == 0)//输入end 跳出循环  关闭客户端
        {
            break;
        }
        send(sockfd, buff, strlen(buff) - 1, 0);
        memset(buff, 0, 128);//清空  下一次重新输入;
        recv(sockfd, buff, 127, 0);
        printf("buff=%s
", buff);
    }
    close(sockfd);//客户端关闭
    exit(0);
}
经验分享 程序员 微信小程序 职场和发展