栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

Linux网络编程——简单基于TCP协议的服务器/客户端示例

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Linux网络编程——简单基于TCP协议的服务器/客户端示例

说明:
  本文章旨在总结备份、方便以后查询,由于是个人总结,如有不对,欢迎指正;另外,内容大部分来自网络、书籍、和各类手册,如若侵权请告知,马上删帖致歉。
  QQ 群 号:513683159 【相互学习】
内容来源:
  《Linux网络编程》

功能描述:

  客户端连接服务器后从标准输入读取字符串发送给服务器。
  服务器接收到字符串后,发送接收到的总字符串个数给客户端、
  客户端将接受到的服务器信息打印到标准输出。
  整个过程流程如下:

源文件 服务器端源文件:tcp_server.c
#include 
#include 
#include 
#include           
#include 
#include 
#include 

#define PORT 8888                                    //侦听端口地址:8888
#define BACKLOG 2                                    //侦听队列长度:2

extern void process_conn_server(int s);              //服务器对客户端的处理:读取数据并发送响应字符  

int main(int argc,char *argv[])
{
	int ss = 0;                                      //ss = server socket = 服务器socket描述符
    int cs = 0;                                      //cs = client socket = 客户端socket描述符
    struct sockaddr_in server_addr;                  //服务器地址结构
    struct sockaddr_in client_addr;                  //客户端地址结构
    int ret = 0;                                     //返回值
    pid_t pid;                                       //进程ID

    
    ss = socket(AF_INET,SOCK_STREAM,0);              //创建一个AF_INET族的流类型socket
    if(ss < 0)                                       //检查是否正常创建socket
    {
        perror("socket errorn");
        exit(EXIT_FAILURE);
    }
    
    
    bzero(&server_addr,sizeof(server_addr));          //清零
    server_addr.sin_family = AF_INET;                 //设置地址族为AF_INET
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);  //本地地址
	server_addr.sin_port = htons(PORT);               //设置端口号 
	   
    
    ret = bind(ss,(struct sockaddr*)&server_addr,sizeof(server_addr));
    if (ret < 0)                                      //出错
    {
        perror("bind errorn");
        exit(EXIT_FAILURE);
    }

    
    ret = listen(ss,BACKLOG);
    if (ret < 0)                                      //出错
    {
        perror("bind errorn");
        exit(EXIT_FAILURE);
    }

    
    for(;;)
    {
        
        int addrlen = sizeof(struct sockaddr);
        cs = accept(ss,(struct sockaddr*)&client_addr,&addrlen);
        if(cs < 0)                                    //出错
        {
            continue;                                 //结束本次循环
        }

        
        pid = fork();                                 //创建新进程
        if(pid < 0)         
        {
            printf("fork errorn");
        }
        else if(pid == 0)   
        {
            close(ss);                                //子进程中关闭服务器的侦听
            process_conn_server(cs);                  //处理连接                             
        }
        else                            
        {
            close(cs);                                //父进程中关闭客户端的连接
        }
    }
	return 0;
}
客户端源文件:tcp_client.c

#include 
#include 
#include 
#include           
#include 
#include 
#include 
#include 

#define PORT 8888                                     //端口地址:8888
 
extern void process_conn_client(int s);

int main(int argc,char *argv[])
{
    int s = 0;                                        //socket描述符        
    struct sockaddr_in server_addr;                   //服务器地址结构  
    int ret = 0;                                      //返回值

    
    s = socket(AF_INET,SOCK_STREAM,0);                //创建一个AF_INET族的流类型socket
    if(s < 0)                                         //检查是否正常创建socket
    {
        perror("socket errorn");
        exit(EXIT_FAILURE);
    }

    
    bzero(&server_addr,sizeof(server_addr));          //清零
    server_addr.sin_family = AF_INET;                 //设置地址族为AF_INET
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);  //本地地址
	server_addr.sin_port = htons(PORT);               //设置端口号 

    
    inet_pton(AF_INET,argv[1],&server_addr.sin_addr);

    
    connect(s,(struct sockaddr*)&server_addr,sizeof(struct sockaddr));
    process_conn_client(s);                           //客户端处理过程
    close(s);                                         //关闭连接
}
处理源文件:tcp_process.c
#include 
#include 
#include 



void process_conn_server(int s)
{
    ssize_t size = 0;
    char buffer[1024];                              //数据的缓冲区

    for (;;)                                        //循环处理过程
    {
        size = read(s,buffer,1024);                 //从套接字中读取数据放到缓冲区buffer中

        if(size == 0)                               //没有数据
        {
            return;
        }

        
        sprintf(buffer,"%ld bytes altogethern",size);
        write(s,buffer,strlen(buffer)+1);           //发给客户端
    }
    
}



void process_conn_client(int s)
{
    ssize_t size = 0;
    char buffer[1024];                                //数据的缓冲区

    for(;;)
    {
        
        size = read(0,buffer,1024);
        if(size > 0)                                  //读到数据
        {
            write(s,buffer,size);                     //发送给服务器
            size = read(s,buffer,1024);               //从服务器读取数据
            write(1,buffer,size);                     //写到标准输出,0表示标准输入,1表示标准输出
        }
    }
}
Makefile文件
all:client server												#all规则,依赖于client和server规则

client:tcp_process.o tcp_client.o								#client规则,生成客户端可执行程序
        gcc -o client tcp_process.o tcp_client.o
server:tcp_process.o tcp_server.o								#server规则,生成服务器端可执行程序
        gcc -o server tcp_process.o tcp_server.o
clean:															#清理规则,删除client、server和中间文件
        rm -f client server *.o
编译并运行

  将上面文件全部置于同一目录下。
  1️⃣编译:
    执行命令:make,结果如下:

cc    -c -o tcp_process.o tcp_process.c					#生成tcp_process.o中间文件
cc    -c -o tcp_client.o tcp_client.c					#生成tcp_client.o中间文件
gcc -o client tcp_process.o tcp_client.o				#由tcp_process.o与tcp_client.o生成可执行文件:client 
cc    -c -o tcp_server.o tcp_server.c					#生成tcp_server.o中间文件
gcc -o server tcp_process.o tcp_server.o				#由tcp_process.o与tcp_server.o生成可执行文件:server 

  2️⃣运行:
    ①打开终端,执行命令:./server
    会执行服务端可执行程序server,该程序会在端口8888上侦听,等待客户端的连接请求。
    ②另起终端,执行命令:./client 127.0.0.1
    会执行服务端可执行程序client ,该程序会连接上服务器
    紧接着输入字符串就会有相应,效果如下:

hhb@xsndz:/home/hhb/桌面/tcp$ ./client 127.0.0.1
nihao
6 bytes altogether
shiyishi
9 bytes altogether
查询网络连接情况

  在程序正常运行的状态,再另起终端,使用netstat命令查询网络连接情况。
  执行指令:netstat,效果如下:

激活Internet连接 (w/o 服务器)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 localhost:39460         localhost:8888          ESTABLISHED
tcp        0      0 localhost:8888          localhost:39460         ESTABLISHED

  其中8888为服务器端的端口,39460为客户端的端口
  服务器和客户端段通过这两个端口建立了连接。

服务器端与客户端程序设计模式

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/460896.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号