Linux学习-通信-Socket封装

本文围绕Linux Socket编程展开,先介绍将server.c和client.c中的socket函数封装进头文件的步骤,包括修改代码、合并封装函数、编写头文件等。接着阐述两端代码编写及编译过程,针对编译时找不到头文件和函数的问题给出解决办法。最后说明运行两端代码的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 进行头文件的编写
将server.c中的socket函数和client.c中的socket函数封装进去头文件,这样就可以直接在服务端或客户端直接进行调用,不需要每次都编写socket函数。

1.1 对server.c进行修改。
原代码可参照上一篇笔记——Linux学习-通信-Socket编写

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
//#include <linux/in.h>
#include <stdlib.h>
#include <string.h>
//头文件不发生改变。

int socketServerCreate(char *ip,char *port) //自定义函数名,这里传参由main函数传
{
	
	struct sockaddr_in s_addr;
	
	memset(&s_addr,0,sizeof( struct sockaddr_in));

	//1.socket
	int s_fd;

	s_fd=socket(AF_INET,SOCK_STREAM,0);
	if(s_fd==-1)
	{
		perror("socket");
		exit(-1);
	}

	s_addr.sin_family=AF_INET;
	s_addr.sin_port=htons(atoi(port));
	inet_aton(ip,&s_addr.sin_addr);
	
	//2.bind
	
	bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));

	//3.listen

	listen(s_fd,10);
	
	return s_fd;
}
//做到listen()函数即可

1.2. 对Client.c进行修改。
原代码可参照上一篇笔记——Linux学习-通信-Socket编写

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
//#include <linux/in.h>
#include <stdlib.h>
#include <string.h>

int socketClientCreate(char*ip,char *port)//自定义函数名,这里传参由main函数传
{
	
	struct sockaddr_in c_addr;
	memset(&c_addr,0,sizeof( struct sockaddr_in));

	//1.socket
	int c_fd;
	c_fd=socket(AF_INET,SOCK_STREAM,0);
	if(c_fd==-1)
	{
		perror("socket");
		exit(-1);
	}

	c_addr.sin_family=AF_INET;
	c_addr.sin_port=htons(atoi(port));
	inet_aton(ip,&c_addr.sin_addr);
	
	//2.connect
	int c_connect=connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr));
	if(c_connect==-1)
	{
		perror("connect");
		exit(-1);
	}
	
	return c_fd;//返回客户端通信的标识符。
}

1.3 将server.c和client.c合并写自己的封装函数

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
//#include <linux/in.h>
#include <stdlib.h>
#include <string.h>

//服务端部分

int socketServerCreate(char *ip,char *port)
{
	struct sockaddr_in s_addr;
	memset(&s_addr,0,sizeof( struct sockaddr_in));

	//1.socket
	
	int s_fd;
	s_fd=socket(AF_INET,SOCK_STREAM,0);
	if(s_fd==-1)
	{
		perror("socket");
		exit(-1);
	}

	s_addr.sin_family=AF_INET;
	s_addr.sin_port=htons(atoi(port));
	inet_aton(ip,&s_addr.sin_addr);
	
	//2.bind
	
	bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));

	//3.listen

	listen(s_fd,10);
	
	return s_fd;
}

//客户端部分
int socketClientCreate(char*ip,char *port)
{
	
	struct sockaddr_in c_addr;
	memset(&c_addr,0,sizeof( struct sockaddr_in));

	//1.socket
	
	int c_fd;
	c_fd=socket(AF_INET,SOCK_STREAM,0);
	if(c_fd==-1)
	{
		perror("socket");
		exit(-1);
	}

	c_addr.sin_family=AF_INET;
	c_addr.sin_port=htons(atoi(port));
	inet_aton(ip,&c_addr.sin_addr);
	
	//2.connect

	int c_connect=connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr));
	if(c_connect==-1)
	{
		perror("connect");
		exit(-1);
	}
	
	return c_fd;
}

自定义封装函数名,我这里用的是mySocketAPI.c

1.4 编写头文件
头文件仅需要mySocketAPI.c中的头部分和声明部分即可。

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
//#include <linux/in.h>
#include <stdlib.h>
#include <string.h>


int socketServerCreate(char *ip,char *port);//记得加分号

int socketClinentCreate(char*ip,char *port);

自定义头函数名,我这里用的是mySocketAPI.h

1.5总结
经过以上4个步骤,头文件已经成功地写好,后面编写server.c和client.c时,只需要调用头文件中的socketSocketCreate()和socketClinentCreate()即可。

2.两端代码编写以及编译

2.1server.c的编写

#include<stdio.h>
#include"mySocketAPI.h"//这里用“”而不用<>的原因,下文会解释

int main(char *argc,char **argv)
{
	int s_fd;
	int c_fd;
	char buf[32] = {};
	
	s_fd = socketServerCreate(argv[1],argv[2]);//仅用一行代码调用头文件中的函数。
	
	while(1){
		c_fd = accept(s_fd,NULL,NULL);
		read(c_fd,buf,32);
		printf("get msg:%s\n",buf);
	
	}

	return 0;
}

2.2client.c的编写

#include<stdio.h>
#include"mySocketAPI.h"

int main(char *argc,char **argv)
{
	int c_fd;
	char *msg = "hello,this is client!";

	c_fd = socketClientCreate(argv[1],argv[2]);
	
	if(c_fd != -1){
		write(c_fd,msg,strlen(msg));	

	}

	return 0;
}

2.3 两端代码的编译
如果代码中用的<>写头文件,如下图:
在这里插入图片描述
会提示找不到头文件,如图:
在这里插入图片描述
原因: 编译器在编译时候会默认从 /user / include / 文件夹下面去找头文件。而我们自己封装的头文件不在此目录。这里有两种解决办法。

方法①:将声明头文件中的 <> 改为 “” 即可。如图:
在这里插入图片描述
改为引号之后,编译器编译时就会从当前目录寻找这个头文件。
找不到时候再去 /user / include / 寻找。

再次编译时候会出现这个问题。如图:
在这里插入图片描述
提示找不到socketServerCreate这个函数,这里需要将socket.c和mySocketAPI.c一起编译即可。
在这里插入图片描述
方法②: 不改变声明头文件中的 <>
在编译时候知名头文件的位置。这里用 -I 来知名头文件地址,如图:
在这里插入图片描述
解决编译问题后,将客户端端代码也编译。如图;
在这里插入图片描述
3. 运行两端代码

运行服务端代码:
在这里插入图片描述
运行客户端代码:
在这里插入图片描述
服务端接收到信息:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值