首页 > 系统相关 >Linux实验八:流式套接字编程

Linux实验八:流式套接字编程

时间:2024-06-15 22:04:23浏览次数:21  
标签:addr buffer 流式 server client fd Linux 接字

目录


一、实验目的

1、深入理解 TCP/IP 模型相关概念;
2、掌握流式套接字 socket 相关的数据结构,如 sokkaddr,sockaddr_in 等;
3、掌握流式套接字通讯时常用的函数,如 socket,connect,listen,accept 等。

二、实验内容

在网络环境中使用流式套接字完成以下内容:客户端进程 A 向服务器进程 B 发送一个字符,B进程将接收到 A 进程的字符,反之亦然。

实验的主要内容是编写一个TCP客户端程序,该程序能够连接到指定的服务器地址和端口,发送用户输入的消息,并接收服务器的回复。在这个过程中,我们需要完成以下关键步骤:

  1. 创建套接字:利用socket()函数创建一个TCP套接字。
  2. 设置服务器地址:配置服务器的IP地址和端口号。
  3. 连接服务器:使用connect()函数连接到服务器。
  4. 数据交互:通过write()和read()函数实现与服务器的数据交换。
  5. 关闭套接字:在通信结束后,关闭套接字释放资源。

三、实验环境

虚拟机软件:VMware 16 Pro
Linux操作系统版本:CentOS-7-64位

四、参考代码

blockserver.c

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define BUFSIZE 1024
#define PORT 5058

int main(int argc, char *argv[]){
    int listen_fd, client_fd;
    struct sockaddr_in server_addr,client_addr;
    ssize_t server_len, client_len ;
    char buffer[BUFSIZE];
    int real_read = -1;

    memset(buffer, BUFSIZE, 0);

    // create socket, socket just like file descriptor
    listen_fd = socket(PF_INET, SOCK_STREAM, 0); 
    server_addr.sin_family = AF_INET; 
    server_addr.sin_port = htons(PORT);
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_len = sizeof(struct sockaddr_in);

    // bind listen_fd and server socket address
    bind(listen_fd, (struct sockaddr *) &server_addr, server_len);

    // set listen queue
    listen(listen_fd, 5);
    // wait for client to connect
    // note: accept's third argment is client socket address's pointer
    client_len = sizeof(struct sockaddr_in);
    client_fd = accept(listen_fd, (struct sockaddr *) &client_addr, &client_len);

    while(1){
        real_read = read(client_fd, buffer, BUFSIZE);
        printf("FROM CLIENT: %s", buffer);
        if( strncmp(buffer,"END",3) == 0) 
            break;
        fgets(buffer, BUFSIZE,stdin);
        write(client_fd, buffer,real_read);  // echo
        memset(buffer,BUFSIZE, 0);
    }

    close(client_fd);
    close(listen_fd);
    return 0; 
}

blockclient.c

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

#define BUFSIZE 1024
#define PORT 5058
 
int main(int argc, char* argv[]){
    int server_fd;
    struct sockaddr_in server_addr;
    char buffer[BUFSIZE];    

    memset(buffer, BUFSIZE, 0);
    server_addr.sin_family = AF_INET;
    // string -> struct in_addr
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    server_addr.sin_port = htons(PORT);
         
    // create client socket
    server_fd = socket(PF_INET, SOCK_STREAM, 0);

    // connect server 
    connect(server_fd,(struct sockaddr *)  &server_addr, sizeof(server_addr));

    while(1){
        fgets(buffer, BUFSIZE,stdin);
        write(server_fd, buffer, BUFSIZE);
        if(strncmp(buffer,"END",3)==0)
            break;

        memset(buffer, BUFSIZE, 0);
        read(server_fd,buffer,BUFSIZE);
        printf("From Server: %s",buffer);
    }
    
    close(server_fd);
    return 0;
}

五、实验步骤

步骤1. 编辑源代码blockserver.c和blockclient.c

源代码blockserver.c和blockclient.c内容见上述参考代码。

mkdir test8
cd test8
vim blockserver.c
vim blockclient.c

源代码blockserver.c

在这里插入图片描述

  首先,定义了缓冲区大小BUFSIZE和服务器监听的端口号PORT。定义了监听套接字listen_fd和客户端套接字client_fd,以及服务器地址server_addr和客户端地址client_addr结构体。buffer数组用于存储接收和发送的数据,real_read用于记录实际读取的字节数。
  接着,使用memset函数将buffer数组的所有元素初始化为0。创建一个 TCP 套接字,并将其文件描述符存储在listen_fd中。设置服务器地址结构体server_addr的成员,包括地址族为 IPv4 (AF_INET),端口号为PORT,IP 地址为任意可用地址 (INADDR_ANY)。将listen_fd套接字与指定的server_addr绑定,使服务器能够接收客户端连接请求。
  然后,开始监听传入的连接请求,允许最多5个等待连接的队列。接受客户端的连接请求,并创建一个新的套接字client_fd用于与客户端通信。此函数会阻塞程序直到有客户端连接进来。处理通信,在一个无限循环中,服务器从client_fd套接字读取数据到buffer中。如果接收到的数据是 “END”,则退出循环。然后从标准输入 (stdin) 获取数据并将其写回client_fd套接字,实现了简单的回显功能。
  最后,在程序结束时关闭client_fdlisten_fd套接字,释放资源。

源代码blockclient.c

在这里插入图片描述

  首先,定义了缓冲区大小BUFSIZE和服务器监听的端口号PORT。声明了服务器套接字server_fd、服务器地址结构体server_addr和用于存储消息的缓冲区buffer。使用memsetbuffer初始化为0。
  接着设置了服务器地址结构体server_addr的成员:地址族为 IPv4 (AF_INET),服务器 IP 地址为本地回环地址127.0.0.1,端口为PORT。创建了 TCP 套接字server_fd,并使用connect函数连接到指定的服务器地址和端口。
  然后,在一个无限循环中,程序通过fgets获取用户输入的消息存入buffer,然后使用write函数将消息发送给服务器。如果用户输入了 “END”,则退出循环。接着使用read函数读取服务器的响应,将响应打印到控制台。
  最后,在程序结束时关闭客户端套接字server_fd,释放资源。

步骤2. 编译源代码blockserver.c和blockclient.c

gcc blockserver.c -o blockserver -g
gcc blockclient.c -o blockclient -g

在这里插入图片描述

步骤3. 运行可执行程序blockserver和blockclient

在第一个终端中,运行blockserver可执行文件。

./blockserver

在第二个终端中,运行blockclient可执行文件。

./blockclient

接下来,分别在服务端和客户端中输入一些字符串,都能互相接收到信息。

在这里插入图片描述

六、实验结果

运行结果如下:

在这里插入图片描述

七、实验总结

  在本次实验中,我们深入学习了如何在Linux环境下使用流式套接字(TCP套接字)来进行客户端-服务器通信。通过编写一个简单的TCP客户端程序,我们不仅掌握了基础的网络编程知识,还体验了实际动手编程的乐趣和挑战。
  在实验过程中,我首先熟悉了流式套接字的基本概念和相关系统调用。通过查阅资料和阅读代码示例,我逐步理解了每个函数的作用及其参数的含义。例如,socket()函数用于创建套接字,connect()函数用于建立连接,write()和read()函数分别用于发送和接收数据。
  在编写客户端程序时,遇到的第一个挑战是如何正确设置服务器地址结构体sockaddr_in。通过仔细阅读文档并结合代码示例,我了解到需要设置地址族为AF_INET,IP地址可以使用inet_addr()函数转换,端口号则通过htons()函数转换为网络字节序。
  另一个挑战是处理与服务器的通信。在实现循环发送和接收消息时,我学会了使用fgets()来获取用户输入,并通过strncmp()函数判断是否输入了“END”从而决定是否退出循环。同时,通过反复测试和调试,确保程序能够正确地发送和接收数据,并处理可能的错误情况。

标签:addr,buffer,流式,server,client,fd,Linux,接字
From: https://blog.csdn.net/Morse_Chen/article/details/139674443

相关文章

  • Linux环境搭建和项目基础
    GCCGCC原名为GNUC语言编译器(GNUCCompiler)GCC(GNUCompilerCollection,GNU编译器套件)是由GNU开发的编程语言译器。GNU编译器套件包括C、C++、Objective-C、Java、Ada和Go语言前端,也包括了这些语言的库(如libstdc++,libgcj等)GCC不仅支持C的许多“方言”,......
  • Linux的目录结构
    问题产生:在学习Linux的过程中对Linux系统的文件结构感到不解,例如/bin和/usr/bin和/usr/local/bin之间的区别以及各个目录到底是存放什么内容的问题,需要进行进一步的学习!列举一下Linux中比较重要的部分目录:主目录:/root,/home/username用户可执行文件:/bin,/usr/b......
  • 【Linux】进程_4
    文章目录五、进程4.进程状态5.进程优先级6.进程的调度和转换未完待续五、进程4.进程状态当进程属于挂起状态时,进程的可执行程序代码和数据均会被从内存中换入到磁盘中,此时进程的PCB并没有消失,只要操作系统还需要管理这个进程,进程的PCB就需要存在,所以我们可以......
  • linux内存管理(八)- 反向映射RMAP
    这里有一篇博客讲的不错。linux内存管理笔记(三十八)----反向映射_linux反向映射-CSDN博客页表是把虚拟地址映射到物理页面,但是如何根据一个物理页找到所有映射它的pte呢?答案是用反向映射ReverseMapping(RMAP)。这在页面回收中很有用。回收页面需要将到物理页的映射断开(改一下pte......
  • Linux 并发与竞争实验学习
    Linux并发与竞争实验学习原子操作实验这里原子操作就是采用原子变量来保护一个程序运行的完整过程,使用atomic来实现一次只能允许一个应用访问LED,创建atomic.c文件,其实改动内容就是添加原子变量,要在设备结构体数据添加原子变量,具体代码如下:structgpioled_dev{dev_td......
  • Linux vim 文本编辑 操作文本 三种模式
    介绍vi是一个经典的行编辑器,支持模式编辑(包括普通模式、插入模式和命令模式)。vim保留vi核心功能的基础上,增加了多级撤销、语法高亮、插件支持等高级功能。两者的最大区别,简单的来说vim就是vi的增强版三种模式命令模式(CommandMode)默认进入的是命令模式。在这个模式......
  • Linux PM:wakeup count、wakelock、autosleep
     在进行wakeupcount、wakelock、autosleep之前,先参考《Linux电源管理(7)_Wakeupeventsframework(wowotech.net)》。下面简单跟一下,wakeupcount、wakelock、autosleep,及其使用方法。1PM初始化PM子系统初始化:pm_initpm_start_workqueuehibernate_image_size_ini......
  • 15-字符串处理的常用函数——查找字符串,求字符串长度,分割字符串,查找指定字符,比较字符
    15-字符串处理的常用函数——查找字符串,求字符串长度,分割字符串,查找指定字符,比较字符串,连接字符串文章目录15-字符串处理的常用函数——查找字符串,求字符串长度,分割字符串,查找指定字符,比较字符串,连接字符串1.`strstr`1.1示例代码2.`strlen`2.1示例代码3.`strtok`......
  • Linux:vim
    目录1、vim简单介绍2、vim使用2.1、进入vim2.2、模式切换2.3、常用命令2.3.1、进出vim2.3.2、定位2.3.3、查找字符串:2.3.4、替换字符串2.3.5、复制粘贴2.3.6、撤销1、vim简单介绍超强的文本编辑器,在Linux中编写代码比较常用,可以根据不同的语言提供高亮,类似notepad+......
  • Linux 虚拟网络 host gw
    hostgw把host作为网关,通过网关进行数据包传输。使用Containerlab模拟网络a|拓扑b|网络拓扑文件#host-gw.clab.ymlname:host-gwtopology:nodes:gw1:kind:linuximage:vyos/vyos:1.2.8cmd:/sbin/initbinds:-/......