TCP网络程序

1.服务器:

  • 创建socket套接字,用到的是int socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)接口,返回的是套接字描述符
    • 此时的socket只是用于接收新的客户端的链接请求,仅具有listen的作用
  • 绑定地址端口,用到的是int bind(int sockfd,const struct sockaddr*address,socklen_t  address_len)接口,0表示成功,-1表示失败
  • 监听,用到的是int listen(int sockfd,int backlog)
    • backlog是最大并发连接数
    • 监听的作用是告诉操作系统开始接收连接请求,并且处理
    • 操作系统为新的socket创建自己的ip地址和端口
  • 接收连接请求,用到的是accept()接口
    • 从已完成连接的队列里获取一个socket
    • 返回一个新的socket来传输数据
  • 收发数据,用到的是recv(),send()接口
  • 关闭套接字,用到的是close()接口

以实现简单的网络聊天程序为例:

代码如下:

int main(int argc, char *argv[])
{
    if (argc != 3) {
        printf("Usage: ./tcp_server ip port\n");
        return -1;
    }
   
    int listen_fd = -1;
    listen_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (listen_fd < 0) {
        perror("socket");
        return -1;
    }
    struct sockaddr_in lst_addr;
    lst_addr.sin_family = AF_INET;
    lst_addr.sin_port = htons(atoi(argv[2]));
    lst_addr.sin_addr.s_addr = inet_addr(argv[1]);

    socklen_t len = sizeof(struct sockaddr_in);
    int ret = bind(listen_fd, (struct sockaddr*)&lst_addr, len);
    if (ret < 0) {
        perror("bind");
        return -1;
    }
    if (listen(listen_fd, 5) < 0) {
        perror("listen");
        return -1;
    }
    while(1) {
        struct sockaddr_in cli_addr;
        len = sizeof(struct sockaddr_in);
        int new_fd;
        new_fd = accept(listen_fd, (struct sockaddr*)&cli_addr, 
                &len);
        if (new_fd < 0) {
            perror("accept");
            continue;
        }
        while(1) {
   
            char buff[1024] = {0};
            ret = recv(new_fd, buff, 1023, 0);
            if (ret == 0) {
                printf("client shutdown!!\n");
                break;
            }else if (ret < 0) {
                //可以被原谅的错误叫被信号打断或数据没有准备好
                if (errno == EINTR || errno == EAGAIN) {
                    continue;
                }
                break;
            }
            printf("client say:%s\n", buff);
            char tmp[1024] = {0};
            printf("input:");
            fflush(stdout);
            scanf("%s", tmp);
            send(new_fd, tmp, strlen(tmp), 0);
        }
        close(new_fd);
    }
    close(listen_fd);
    return 0;
}

2.客户端

  • 创建套接字,用到的是socket()
  • 绑定地址端口(不建议手动绑定,因为一个端口只能绑定一个客户,很容易绑定失败)
  • 向服务器发送连接请求,用到的是connect()接口
  • 收发数据,用到的是recv()/send()
  • 关闭套接字,close()

代码如下:

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

/*TCP--简单的网络聊天程序--客户端
 *  1. 创建socket                               socket()
 *  2. 为socket绑定地址---客户端不推荐手动绑定  bind()
 *  3. 向服务器端发起连接请求                   connect()
 *  4. 收发数据                                 recv/send
 *  5. 关闭socket                               close
 */
int main(int argc, char *argv[])
{
    if (argc != 3) {
        printf("Usage: ./tcp_client ip port");
        return -1;
    }
    //创建套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sockfd < 0) {
        perror("socket");
        return -1;
    }
    struct sockaddr_in serv_addr;
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(atoi(argv[2]));
    serv_addr.sin_addr.s_addr = inet_addr(argv[1]);

    socklen_t len = sizeof(struct sockaddr_in);
    //向服务器发起连接
    int ret = connect(sockfd, (struct sockaddr*)&serv_addr, len);
    if (ret < 0) {
        printf("connect");
        return -1;
    }
    while(1) {
        char buff[1024] = {0};
        printf("input:");
        fflush(stdout);
        scanf("%s", buff);
        //通过socket发送数据
        send(sockfd, buff, strlen(buff), 0);
        //接收数据
        char tmp[1024] = {0};
        ret = recv(sockfd, tmp, 1024, 0);
        if (ret == 0) {
            printf("peer shutdown !!\n");
            close(sockfd);
            return -1;
        }
        printf("server say:%s\n", tmp);
    }
    close(sockfd);
    return 0;
}

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值