TCP协议--网络编程流程

  TCP 协议是一种面向连接的、可靠的字节流服务。

TCP协议的编程流程

服务器端
socket();//创建一个用于监听客户端连接的网络套接字
bind();//将创建的套接字与本段的地址信息进行绑定
listen();//启动监听,不会阻塞
accept();//接收一个客户端的连接,返回的是一个客户端连接套接字
recv(); /send(); //读取数据或发送数据
close();//关闭文件描述符(套接字)

客户端
socket(); //创建一个用于整个通讯的套接字
connect(); //与服务器建立连接
recv(); /send(); //读取或发送数据
close(); //关闭文件描述符

所涉及到的系统调用用法

 int socket(int domain, int type, int protocol);//成功返回 0 ,失败返回-1

domain:协议族 AF_INET
type:具体的协议 SOCK_STREAM (TCP) SOCK_DGRAM (UDP)
protocol:0 默认

int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);//成功返回0,失败返回 -1

sockfd:使用socket方法创建的套接字描述符
addr:服务器程序的地址信息 IP+端口号
addr_len:指定结构体大小
struct sockaddr
{
sa_family_t sa_family;
char sa_data[14];
};
一般使用sockaddr_in ,用指针类型强转成sockaddr类型的
struct sockaddr_in
{
sa_family_t sin_family; //地址族 AF_INET
unsigned short sin_port; //端口号
struct in_addr sin_addr; // IP地址信息 点分十进制字符串 转换成u_int32_t
};
struct in_addr
{
u_int32_t s_addr;
};

int listen(int sockfd, int backlog);//成功返回0 ,失败返回 -1

sockfd:创建并绑定过的套接字描述符
backlog:指定内核创建的用于维护当前客户端连接(还没被accept)的
队列(已完成连接)的大小
(有两个队列:正在进行连接的 和 已完成连接的)

int accept(int sockfd, struct sockaddr *addr,socklen_t *addrlen);//成功返回与一个客户端连接的文件描述符,失败返回 -1

sockfd:经过listen的监听套接字
addr:用于保存接收到的客户端的地址信息
addrlen:地址结构的长度

ssize_t recv(int sockfd, void *buf, size_t len, int flags);
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);//与服务器进程建立连接  *addr是服务器的地址信息
举例

  在linux下,编写服务器端和客户端代码,服务器端接收客户端的连接,并打印客户端发送过来的数据,代码如下:

/*服务器端*/
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>

int main()
{
    int listenfd=socket(AF_INET,SOCK_STREAM,0);
    assert(listenfd!=-1);

    struct sockaddr_in ser_addr;
    memset(&ser_addr,0,sizeof(ser_addr));
    ser_addr.sin_family=AF_INET;
    ser_addr.sin_port=htons(6000);
    ser_addr.sin_addr.s_addr=inet_addr("127.0.0.1");//回环地址

    int res=bind(listenfd,(struct sockaddr*)&ser_addr,sizeof(ser_addr));
    assert(res!=-1);
    res=listen(listenfd,5);
    assert(res!=-1);

    while(1)
    {
        struct sockaddr_in cli_addr;
        socklen_t len=sizeof(cli_addr);
        int clientLinkFd=accept(listenfd,(struct sockaddr*)&cli_addr,&len);
        if(clientLinkFd==-1)
        {
            printf("one client error\n");
            continue;
        }

        printf("onr client success:--%s:%d\n",inet_ntoa(cli_addr.sin_addr),n    tohs(cli_addr.sin_port));
 
        while(1)
        {
            char buff[128]={0};
            int num=recv(clientLinkFd,buff,127,0);//0--默认方式
            if(num==-1)
            {
                printf("recv error\n");
                break;
            }
            else if(num ==0)
            {
                printf("client over\n");
                break;
            }
            printf("recv data is : %s\n",buff);
 
            char *restr="recv data success";
            num=send(clientLinkFd,restr,strlen(restr),0);
            if(num==-1)
            {
                printf("send data error\n");
                break;
            }
        }
        close(clientLinkFd);
    }
    close(listenfd);
    exit(0);
}
/*客户端*/
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>

int main()
{
    int sockfd=socket(AF_INET,SOCK_STREAM,0);
    assert(sockfd!=-1);

    struct sockaddr_in ser_addr;
    memset(&ser_addr,0,sizeof(ser_addr));
    ser_addr.sin_family=AF_INET;
    ser_addr.sin_port=htons(6000);
    ser_addr.sin_addr.s_addr=inet_addr("127.0.0.1");//回环地址

    int res=connect(sockfd,(struct sockaddr*)&ser_addr,sizeof(ser_addr));
    assert(res!=-1);

    while(1)
    {
        char buff[128]={0};
        printf("input: ");
        fgets(buff,128,stdin);
        if(strncmp(buff,"end",3)==0)
        {
            break;
        }
        send(sockfd,buff,strlen(buff),0);
        memset(buff,0,128);

        recv(sockfd,buff,127,0);
        printf("buff=%s\n",buff);
    }
    close(sockfd);
    exit(0);
}

运行结果如下(注意先启动服务器端):
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值