IP地址:
IP协议有两个版本,一个是IPv4,一个是IPv6。
IP地址是在IP协议中,用来标识网络中不同的主机的地址。
对于IPv4来说,IP地址是一个4字节,32位的整数。
源IP地址和目的IP地址:
在数据包头部的两个IP地址,一个叫源IP地址,一个叫目的IP地址
端口号port(必须是众所周知的,并且不能随意修改):
端口号是一个2个字节,16位的整数
端口号用来标识一个进程,告诉操作系统,当前的这个数据要交给那个进程来处理
IP地址 + 端口号:标识着网络上某一台主机的某一个进程。
源端口号和目的端口号:
可以基本理解为“谁发的,要发给谁”。
认识UDP:
传输层协议、无连接、不可靠传输、面向数据报
网络字节序列:
内存中多字节数据相对于内存地址有大小端之分,网络数据流同样具有大小端之分。
发送主机通常将发送缓冲区的数据按照内存地址从低脂高顺修发出,
接受主机把从网络上接收到的字节依次保存在接收缓存区中,也是按照内存地址从低到高的顺修保存,
因此,网络数据流的地址因该这样规定,先发的数据应该是低地址,后发的数据应该是高地址,
TCP/IP协议规定,网络数据流应该采用大端自己序列,即低地址高字节。
int socket(int domain, int type, int protocol);
1.创建socket文件描述符
int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
2. 绑定端口号
int listen(int s, int backlog);
3.开始监听
int accept(int s, struct sockaddr *addr, socklen_t *addrlen);
4.接收请求
int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
5.建立链接
sockaddr 结构
IPv4和IPv6的地址格式定义在netinet.h中IPv4用结构体sockaddr_in表示,
IPv4和IPv6的地址类型分别定义为常数AF_INET,AF_INET6,这样只要取得了sockaddr结构体的首地址,不需要知道具体是哪一种类型的sockadr结构体,就可以根据地址类型字段确定结构体的内容。
以下是一个简单的UDP服务器。
//服务器
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<stdlib.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<string.h>
#define SIZE 128
//127.0.0.1;本地环回 用于测试本地网络
//netstat -nlp 显示网络接口 比如ssh
void service(int sock)
{
char buf[SIZE];
while(1)
{
struct sockaddr_in peer;
socklen_t len = sizeof(peer);
buf[0] = 0;
size_t s = recvfrom(sock,buf,sizeof(buf)-1,0,(struct sockaddr*)&peer,&len);
if(s>0)
{
buf[s] = 0;
printf("[%s:%d]# %s\n",inet_ntoa(peer.sin_addr),ntohs(peer.sin_port),buf);
sendto(sock,buf,strlen(buf),0,(struct sockaddr*)&peer,len);
}
}
}
int main(int argc,char *argv[])
{
if(argc != 3)
{
printf("Usage:%s [ip] [port]\n",argv[0]);
return 3;
}
int sock = socket(AF_INET,SOCK_DGRAM,0);
if(sock<0)
{
perror("socket");
return 1;
}
struct sockaddr_in local;
local.sin_family = AF_INET;
local.sin_port = htons(atoi(argv[2]));
local.sin_addr.s_addr = inet_addr(argv[1]);
if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)
{
perror("bind");
return 2;
}
service(sock);
close(sock);
return 0;
}
//客户端
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<stdlib.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<string.h>
int main(int argc,char* argv[])
{
if(argc != 3)
{
printf("Usage: %s [ip] [port]\n",argv[0]);
return 1;
}
int sock = socket(AF_INET,SOCK_DGRAM,0);
if(sock<0)
{
perror("socket");
return 2;
}
char buf[128];
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(atoi(argv[2]));
server.sin_addr.s_addr = inet_addr(argv[1]);
socklen_t len = sizeof(server);
while(1)
{
buf[0] = 0;
size_t s = read(0,buf,sizeof(buf)-1);
if(s>0)
{
buf[s-1] = 0;
sendto(sock,buf,strlen(buf),0,(struct sockaddr*)&server,len);
s = recvfrom(sock,buf,sizeof(buf)-1,0,NULL,NULL);
if(s>0)
{
buf[s] = 0;
printf("server # %s\n",buf);
}
}
}
close(sock);
return 0;
}