前言
昨天介绍完了网络编程中常用的api接口使用方法,今天我们开始来进行实战编程学习!
搭建服务器和客户端编程
- IP地址转换实战演示 -
1、首先我们来演示inet_addr这个函数来对ip地址转换:
代码语言:javascript复制 #include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define IPADDR "192.168.1.102"
int main(void)
{
in_addr_t addr = 0;
addr=inet_addr(IPADDR);
printf("the addr is 0x%xn",addr);
return 0;
}
演示结果:
代码语言:javascript复制 ubuntu@ubuntu-virtual-machine:~$ ./a.out
the addr is 0x6601a8c0
说明:这里我们可以看到IP地址点分十进制表示方法被转换成一般形式(这里打印出的是十六进制表示法)。
2、inet_pton对IP地址转换演示:
代码语言:javascript复制#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define IPADDR "192.168.1.102"
int main(void)
{
int net =0;
struct in_addr addr;
net=inet_pton(AF_INET,IPADDR,&addr.s_addr);
if(1!=net)
{
printf("the inet_pton is errorn");
return -1;
}
printf("the addr is = 0x%xn",addr.s_addr);
return 0;
}
演示结果:
代码语言:javascript复制ubuntu@ubuntu-virtual-machine:~$ ./a.out
the addr is = 0x6601a8c0
说明:效果和inet_addr函数一样。
3、inet_ntop对IP地址转换:
代码语言:javascript复制#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(void)
{
char buf[50]={0};
const char *net =NULL;
struct in_addr addr;
addr.s_addr= 0x6703a8c0;
net=inet_ntop( AF_INET,&addr.s_addr,buf,sizeof(buf));
if(NULL==net)
{
printf("the inet_ntop is errorn");
return -1;
}
printf("the addr is %sn",buf);
return 0;
}
演示结果:
代码语言:javascript复制ubuntu@ubuntu-virtual-machine:~$ ./a.out
the addr is 192.168.3.103
说明:这里我们可以看到inet_ntop函数把一般的形式的IP地址转换成点分十进制。
- 搭建服务器 -
- 第一步:调用socket函数来创建套接字。
- 第二步:调用bind函数分配IP地址和端口号。
- 第三步:调用listen函数转为可接收状态。
- 第四步:调用accept函数来处理连接请求。 返回值是一个fd,accept正确返回就表示我们已经和前来连接我的客户端之间建立了一个TCP连接了,以后我们就要通过这个连接来和客户端进行读写操作,读写操作就需要一个fd,这个fd就由accept来返回了,跟我们之前的socketfd是不一样的,这一点要注意。
- 第五步:关闭套接字文件描述符。
- 注意:socket返回的fd叫做监听fd,是用来监听客户端的,不能用来和任何客户端进行读写;accept返回的fd叫做连接fd,用来和连接那端的客户端程序进行读写。
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#define SERPORT 9003
#define SERADDR "192.168.183.140"
// ifconfig看到的
#define BACKLOG 100
int main(void)
{
// 第1步:先socket打开文件描述符
int sockfd = -1, ret = -1, clifd = -1;
socklen_t len = 0;
struct sockaddr_in seraddr = {0};
struct sockaddr_in cliaddr = {0};
//char ipbuf[30] = {0};
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == sockfd)
{
perror("socket");
return -1;
}
printf("socketfd = %d.n", sockfd);
// 第2步:bind绑定sockefd和当前电脑的ip地址&端口号
seraddr.sin_family = AF_INET; // 设置地址族为IPv4
seraddr.sin_port = htons(SERPORT); // 设置地址的端口号信息
seraddr.sin_addr.s_addr = inet_addr(SERADDR); // 设置IP地址
ret = bind(sockfd, (const struct sockaddr *)&seraddr, sizeof(seraddr));
if (ret < 0)
{
perror("bind");
return -1;
}
printf("bind success.n");
// 第三步:listen监听端口
ret = listen(sockfd, BACKLOG);
if (ret < 0)
{
perror("listen");
return -1;
}
// 第四步:accept阻塞等待客户端接入
clifd = accept(sockfd, (struct sockaddr *)&cliaddr, &len);
printf("连接已经建立,client fd = %d.n", clifd );
return 0;
}
说明:上面的服务器的IP地址要根据每个人的电脑来查看(可以使用ifconfig查看,如下买所示),还有函数htons(它表示表示把主机地址转化为网络讯流,这样看到这个函数就知道它的意思,h——表示host,n——表示network,s表示short,就是字节大小,其实通信也要有大小端模式的,就是说双方通信要规定好是同一模式就好,关于大小端模式的介绍,可以看之前的文章——c语言之共用体union、枚举、大小端模式,如下所示):
代码语言:javascript复制 root@ubuntu-virtual-machine:/home/ubuntu# ifconfig
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.183.140 netmask 255.255.255.0
broadcast 192.168.183.255
inet6 fe80::6b81:110c:548f:2f41 prefixlen 64
scopeid 0x20<link>
代码语言:javascript复制 #include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
DESCRIPTION
The htonl() function converts the unsigned integer
hostlong from host
byte order to network byte order.
The htons() function converts the unsigned short
integer hostshort from
host byte order to network byte order.
The ntohl() function converts the unsigned integer
netlong from network
byte order to host byte order.
The ntohs() function converts the unsigned short
integer netshort from
network byte order to host byte order.
On the i386 the host byte order is Least
Significant Byte first,
whereas the network byte order, as used on the
Internet, is Most Sig‐
nificant Byte first.
- 客户端 -
- socket,先创建套接字。
- connect,用来连接服务器的。
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#define SERADDR "192.168.183.140" // 服务器开放给我们的IP地址和端口号
#define SERPORT 9003
int main(void)
{
// 第1步:先socket打开文件描述符
int sockfd = -1, ret = -1;
struct sockaddr_in seraddr = {0};
struct sockaddr_in cliaddr = {0};
// 第1步:socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == sockfd)
{
perror("socket");
return -1;
}
printf("socketfd = %d.n", sockfd);
// 第2步:connect链接服务器
seraddr.sin_family = AF_INET; // 设置地址族为IPv4
seraddr.sin_port = htons(SERPORT); // 设置地址的端口号信息
seraddr.sin_addr.s_addr = inet_addr(SERADDR); // 设置IP地址
ret = connect(sockfd, (const struct sockaddr *)&seraddr, sizeof(seraddr));
if (ret < 0)
{
perror("listen");
return -1;
}
printf("connect result, ret = %d.n", ret);
return 0;
}
最终结果(这里只是暂时实现服务器和客户端通信,后面再实现更多功能):