【手把手教你写服务器】客户端程序和服务器程序的简单实现

1.基本TCP客户/服务器程序的套接字函数

下图中各个函数的功能、参数及返回值自行查阅《UNIX网络编程卷1:套接字联网API》第4章。

在这里插入图片描述

2.server.c

#include <stdio.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>

#define SERV_PORT 9000 // 本服务器要监听的端口号,一般1024以下的端口很多都是周知端口,所以这里采用1024之后的数字做端口号

int main(int argc, char* const* argv)
{
    int listenfd = socket(AF_INET, SOCK_STREAM, 0); // 创建服务器的socket套接字(文件描述符)

    struct sockaddr_in serv_addr; // 服务器的地址结构体

    memset(&serv_addr, 0, sizeof(serv_addr));
    
    // 设置本服务器要监听的地址和端口,这样客户端才能连接到该地址和端口并发送数据
    serv_addr.sin_family = AF_INET; // 选择协议族为IPV4
    serv_addr.sin_port = htons(SERV_PORT); // 绑定我们自定义的端口号,客户端程序和服务器程序通讯时,就要往这个端口连接和传送数据
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 监听本地所有的IP地址,INADDR_ANY表示一个服务器上所有的网卡(服务器可能不止一个网卡),多个本地ip地址都进行绑定端口号,进行侦听    

    bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); // 绑定服务器地址结构体

    listen(listenfd, 32); // 第二个参数表示服务器可以积压的未处理完的连入请求总个数,客户端来一个未连入的请求,请求数+1,连入请求完成、c/s之间进入正常通讯后,请求数-1

    int connfd;

    const char *pcontent = "I sent sth to client!"; // 指向常量字符串区的指针

    for (;;)
    {
        // 卡在这里,等客户端连接,客户端连入后,该函数走下去
        // 注意这里返回的是一个新的socket(connfd),后续本服务器就用connfd和客户端之间收发数据,而原有的lisenfd依旧用于继续监听其他连接
        connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);

        // 发送数据包给客户端
        write(connfd, pcontent, strlen(pcontent)); // 注意第一个参数是accept()返回的connfd套接字
        
        // 只给客户端发送一个信息,然后直接关闭套接字连接
        close(connfd);
    }

    close(listenfd); // 实际上本程序走不到这里,一直在上面循环

    return 0;
}

在这里插入图片描述

3.client.c

#include <stdio.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>

#define SERV_PORT 9000 // 要连接到的服务器端口,服务器必须在这个端口上listen着

int main(int argc, char* const* argv)
{
    int sockfd = socket(AF_INET, SOCK_STREAM, 0); // 创建客户端的socket

    struct sockaddr_in serv_addr;

    memset(&serv_addr, 0, sizeof(serv_addr));

    // 设置要连接到的服务器的信息
    serv_addr.sin_family = AF_INET; // 选择协议族为IPV4
    serv_addr.sin_port = htons(SERV_PORT); // 连接到的服务器端口,服务器监听这个地址

    // 这里为了方便演示,要连接的服务器地址固定写
    if (inet_pton(AF_INET, "192.168.43.126", &serv_addr.sin_addr) <= 0) // IP地址转换函数,把第二个参数对应的ip地址转换第三个参数里边去
    {
        printf("调用inet_pton()失败,退出!\n");
        exit(1);
    }

    // 连接到服务器
    if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
    {
        printf("调用connect()失败,退出!\n");
        exit(1);
    }

    int n;
    char recvline[1000 + 1];

    while ((n = read(sockfd, recvline, 1000)) > 0) // 仅供演示,非商用,所以不检查收到的宽度
    {
        recvline[n] = 0; // 实际商业代码要判断是否收取完毕等等,所以这个代码只有学习价值,并无商业价值
        printf("收到的内容为:%s\n", recvline);
    }
    
    close(sockfd); // 关闭套接字
    
    printf("程序执行完毕,退出!\n");
    
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值