Linux下的TCP/IP编程----实践篇

在了解了socket编程的基础知识之后就可以开始尝试编写一个简单的TCP/IP的服务端/客户端程序了。

首先来梳理一下卡客户端和服务端的操作流程:

服务端:

创建socket——绑定地址(IP地址+端口地址)——监听连接请求——接受连接请求——进行数据交换

#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>
//函数声明
void error_handling(char *message);

int  main(int argc,char  *argv[ ] ){

    //客户端和服务端的socket描述符
    int  serv_sock;
    int clent_sock;
    //客户端和服务端的地址
    struct sockaddr_in serv_addr;
    struct sockaddr_in clent_addr;

    //客户端地址大小
    socklen_t  client_addr_size;

    //要发送的消息
    char messages [] = {"Hello World"};

    if(argc!=2){
        printf("Usage : %s  <port> \n",argv[0]);
        exit(1);
    }

    //设置服务端socket使用的协议和连接方式
    serv_sock = socket(PF_INET,SOCK_STREAM,0);
    //进行检查
    if(serv_sock == -1){
        error_handling("socket() error");
    }
    //初始化server_addr所申请的内存空间
    memset(&serv_addr,0,sizeof(serv_addr));

    //为serve_addr结构体设置使用协议,IP地址,端口号
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_addr.sin_port = htons(atoi(argv[1]));
    //进行地址绑定
    if(bind(serv_sock,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) == -1){
        error_handling("bind() error");
    }

    //设置监听
    if(listen(serv_sock,5) == -1){
        error_handling("listen() error");
    }
    //获取客户端的地址大小
    client_addr_size = sizeof(clent_addr);

    //监听到后接收请求,并使用服务端本地的客户端代理,以便于服务端能继续接受新的连接请求
    clent_sock = accept(serv_sock,(struct sockaddr *) &clent_addr,&client_addr_size);

    if(clent_sock == -1){
        error_handling("accept() error");
    }

    //向客户端传送数据
    write(clent_sock,messages,sizeof(messages));
    close(clent_sock);
    close(serv_sock);

    return 0;
}

//出错处理
void error_handling(char * message){
    fputs(message,stderr);
    fputc('\n',stderr);
    exit(1);
}

客户端:

创建socket——输入服务端地址和端口号进行连接请求——进行数据的交换

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

void error_handling(char *message);

int main(int argc,char* argv[]){
    //本地socket描述符
    int socket;
    //服务端socket地址
    struct sockaddr_in server_addr;
    //存储接收到的字符串
    char message[30];
    //接收到的字符串长度
    int str_len;

    //检查参数的个数是否合法
    if(argc != 3){
        printf("Usage : %  <IP> <PORT> \n",argv[0]);
        exit(1);
    }

    //创建客户端的socket,并指定使用协议,连接方式。
    socket  = socket(PF_INET,SOCK_STREAM,0);
    //初始化server_addr所申请的内存空间
    memset(&server_addr,0,sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr(argv[1]);
    server_addr.sin_port = htons(atoi(argv[2]));

    //进行连接请求
    if(connect(socket,(struct sockaddr *) &server_addr,sizeof(server_addr)) == -1){
        error_handling("connect() error");
    }

    //连接成功则读取数据
    str_len = read(socket,message,sizeof(message));
    if(str_len == -1){
        error_handling("read() error");
    }

    //打印接收到的信息
    printf("message from Server : %s \n ",message);
    close(socket);

    return 0;
}

void error_handling(char * message){
    fputs(message,stderr);
    fputc('\n',stderr);
    exit(1);
}

编译运行:

编译服务端程序:

weiqingcai@weiqingcai-Inspiron-7447:~/桌面 $ cd studyProjects/
weiqingcai@weiqingcai-Inspiron-7447:~/桌面/studyProjects $ gcc -o server server.c

编译客户端程序:

weiqingcai@weiqingcai-Inspiron-7447:~/桌面 $ cd studyProjects/
weiqingcai@weiqingcai-Inspiron-7447:~/桌面/studyProjects $ gcc -o client client.c

首先运行服务端:

weiqingcai@weiqingcai-Inspiron-7447:~/桌面/studyProjects $ ./server 9999

之后命令行光标会一直不动,等待连接请求。

然后运行客户端:

weiqingcai@weiqingcai-Inspiron-7447:~/桌面/studyProjects $ ./client 127.0.0.1 9999
message from Server : Hello World

消息会直接从服务端返回,同时服务端也结束运行

至此一个简单的服务端/客户端的程序就写好了。

梳理一遍整个流程:

首先服务端要先运行起来,保证客户端请求时能够给出响应。服务端程序要先创建自己的套接字,然后为套接字绑定地址(IP地址和端口号),然后使其进入监听状态,在有客户端请求时需要接受客户端请求,进行通讯。

对于客户端而言,首先建立自己的socket,然后就是请求连接服务端,在连接成功之后就可以进行数据的读写。

然后我们可以对这个简单的服务端/客户端程序进行不断的完善

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值