前言
昨天介绍完了网络编程中常用的api接口使用方法,今天我们开始来进行实战编程学习!
搭建服务器和客户端编程
- IP地址转换实战演示 -
1、首先我们来演示inet_addr这个函数来对ip地址转换:
#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%x\n",addr);
return 0;
}
演示结果:
ubuntu@ubuntu-virtual-machine:~$ ./a.out
the addr is 0x6601a8c0
说明:这里我们可以看到IP地址点分十进制表示方法被转换成一般形式(这里打印出的是十六进制表示法)。
2、inet_pton对IP地址转换演示:
#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 error\n");
return -1;
}
printf("the addr is = 0x%x\n",addr.s_addr);
return 0;
}
演示结果:
ubuntu@ubuntu-virtual-machine:~$ ./a.out
the addr is = 0x6601a8c0
说明:效果和inet_addr函数一样。
3、inet_ntop对IP地址转换:
#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 error\n");
return -1;
}
printf("the addr is %s\n",buf);
return 0;
}
演示结果:
ubuntu@ubuntu-virtual-machine:~$ ./a.out
the addr is 192.168.3.103
说明:这里我们可以看到inet_ntop函数把一般的形式的IP地址转换成点分十进制。
- 搭建服务器 -
#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、枚举、大小端模式,如下所示):
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>
#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.
- 客户端 -
#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;
}
最终结果(这里只是暂时实现服务器和客户端通信,后面再实现更多功能):