TCP的框架

本文详细介绍了如何使用C语言进行TCP套接字编程,包括服务端的创建套接字、绑定、监听、接受连接以及消息收发,以及客户端的创建连接和消息收发。整个过程涉及IPV4、端口、套接字操作函数如socket、bind、listen、accept、recv和send等。

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

服务端

  1. 创建套接字
  2. 绑定信息
  3. 监听
  4. 建立连接
  5. 收发消息
  6. 关闭套接字

1.创建套接字

//创建套接字
int serfd = 0;
serfd = socket(AF_INET, SOCK_STREAM, 0);
第一个参数:IP的类型 IPV4 --- AF_INET
                  IPV6 --- AF_INET6
第二个参数:通信的协议类型,有两种TCP和UDP
                  TCP --- SOCK_STREAM 
                  UDP --- SOCK_DGRAM 
第三个参数:写0,基本上已经废弃了

2.绑定信息

//2.绑定
if((bind(serfd, (struct sockaddr *)&seraddr, sizeof(seraddr))) < 0)
{
    perror("bind");
    return -1;
}
printf("bind OK!\n");
第一个参数:填写创建的套接字
第二个参数:填写定义的核心结构体,在这里要进行强制类型转换,因为我们定义的结构体是 struct sockaddr_in .但是在bind函数中默认使用的还是原来的 struct sockaddr .后面取地址 &seraddr 这个是什么主要看的是针对的是服务端还是客户端
第三个参数:核心结构体的大小

3.监听

#include <sys/types.h>          
#include <sys/socket.h>
int listen(int sockfd, int backlog);
在网络通信中, 客户端通常处于主动的一方, 而服务器则是被动的一方, 服务器是被连接的, 所以他要时刻准备着被连接, 所以就需要调用 listen() 来监听, 等着被连接.
listen() 函数的主要作用就是将 socket() 函数得到的 sockfd 变成一个被动监听的套接字, 用来被动等待客户端的连接, 而参数 backlog 的作用就是设置连接队列的长度

4.建立连接

//4.建立连接
    socklen_t len = sizeof(cliaddr);
    clifd = accept(serfd,(struct sockaddr*)&cliaddr,&len);
    if(clifd < 0)
    {
        perror("accept");
        return -1;
    }
    printf("连接成功\n");
第一个参数:socket创建的套接字
第二个参数:填写定义的核心结构体,在这里要进行强制类型转换,因为我们定义的结构体是 struct sockaddr_in .但是在bind函数中默认          使用的还是原来的 struct sockaddr .后面取地址 &seraddr 这个是什么主要看的是针对的是服务端还是客户端,因为是要和客          户端建立连接,因此是 &cliaddr 
第三个参数:核心结构体的大小

5.消息的收发

//5.收发消息
    while (1)
    {
        memset(buf,0,sizeof(buf));
        recv(clifd,buf,sizeof(buf),0);
        printf("来自%s的消息:%s\n",inet_ntoa(cliaddr.sin_addr),buf);
        memset(buf,0,sizeof(buf));
        printf("请输入你要发送的消息:\n");
        scanf("%s",buf);
        send(clifd,buf,sizeof(buf),0);
    }
接收消息
    recv(clifd,buf,sizeof(buf),0);
    第一个参数:新的套接字,就是accept的返回值,套接字clifd
    第二个参数:接收消息内存
    第三个参数:接收消息的缓存区的大小
    第四个参数:填写 0 --- 阻塞
                   1 --- 非阻塞
    inet_ntoa(cliaddr.sin_addr):将32位网络字节序转换为点分十进制。例:192.168.110.110
发送消息
    send(clifd,buf,sizeof(buf),0);
    第一个参数:新的套接字,就是accept的返回值,套接字clifd
    第二个参数:接收消息内存
    第三个参数:接收消息的缓存区的大小
    第四个参数:填写 0 --- 阻塞
                   1 --- 非阻塞

6.关闭套接字

//6.关闭
    close(serfd);
    close(clifd);

客户端

  1. 创建套接字
  2. 建立连接
  3. 收发消息
  4. 关闭套接字

1.创建套接字

创建套接字的操作和服务端的操作一样

2.建立连接

int net = connect(serfd, (struct sockaddr*)&seraddr, sizeof(seraddr));
if(net < 0)
{
    perror("connect");
    return -1;
}
printf("连接服务器成功\n");
第一个参数:套接字
第二个参数:核心结构体
第三个参数:核心结构体的大小

3.消息的收发

消息的收发的操作和服务端的操作一样

4.关闭套接字

关闭套接字的操作和服务端的操作一样

服务端完整代码 

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define PORT  6666
#define IP "192.168.149.128"
int main(int argc,char *argv[])
{
    //1.创建套接字
    int serfd = 0,clifd = 0;
    char buf[1024];
    struct sockaddr_in seraddr,cliaddr;
    serfd = socket(AF_INET,SOCK_STREAM,0);
    if(serfd < 0)
    {
        perror("socket");
        return -1;
    }
    printf("创建成功%d\n",serfd);
    memset(&seraddr,0,sizeof(seraddr));
    memset(&cliaddr,0,sizeof(cliaddr));
    seraddr.sin_family = AF_INET;//IPV4
    seraddr.sin_port = htons(PORT);//端口号
    seraddr.sin_addr.s_addr = inet_addr(IP);
    //2.绑定
    if((bind(serfd,(struct sockaddr*)&seraddr,sizeof(seraddr)))<0)
    {
        perror("bind");
        return -1;
    }
    printf("绑定成功\n");
    //3.监听
    if((listen(serfd,10))<0)
    {
        perror("listen");
        return -1;
    }
    printf("监听成功\n");
    //4.建立连接
    socklen_t len = sizeof(cliaddr);
    clifd = accept(serfd,(struct sockaddr*)&cliaddr,&len);
    if(clifd < 0)
    {
        perror("accept");
        return -1;
    }
    printf("连接成功\n");
    //5.收发消息
    while (1)
    {
        memset(buf,0,sizeof(buf));
        recv(clifd,buf,sizeof(buf),0);
        printf("来自%s的消息:%s\n",inet_ntoa(cliaddr.sin_addr),buf);
        memset(buf,0,sizeof(buf));
        printf("请输入你要发送的消息:\n");
        scanf("%s",buf);
        send(clifd,buf,sizeof(buf),0);
    }
    //6.关闭
    close(serfd);
    close(clifd);
    return 0;
}

客户端完整代码

 

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define PORT  6666
#define IP "192.168.149.128"
int main(int argc, char *argv[])
{
    int serfd = 0;
    struct sockaddr_in seraddr;
    serfd = socket(AF_INET, SOCK_STREAM, 0);
    if(serfd < 0)
    {
        perror("socket");
        return -1;
    }
    printf("创建套接字成功\n");
    memset(&seraddr,0,sizeof(seraddr));
    seraddr.sin_family = AF_INET;//ipv4
    seraddr.sin_addr.s_addr = inet_addr(IP);
    seraddr.sin_port = htons(PORT);
    int net = connect(serfd, (struct sockaddr*)&seraddr, sizeof(seraddr));
    if(net < 0)
    {
        perror("connect");
        return -1;
    }
    printf("连接服务器成功\n");
    char buf[1024];
    while(1)
    {
        memset(buf,0,sizeof(buf));
        printf("请输入你要发送的消息:\n");
        scanf("%s",buf);
        send(serfd,buf,sizeof(buf),0);
        memset(buf,0,sizeof(buf));
        recv(serfd,buf,sizeof(buf),0);
        printf("来自服务器的消息:%s\n",buf);    
    }
    close(serfd);
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值