——————sockaddr结构
socket API是一层抽象的网络编程接口,适用于各种底层网络协议,如IPv4、IPv6等,然而各种网络协议的地址格式格式并不同
虽然socket api的接口是sockaddr,但是我们真正在基于IPv4编程时,使用的数据结构是sockaddr_in,这个结构主要有三部分信息:地址列席、端口号、IP地址
————————————————————
简单的UDP网络程序
回显服务器(Echo Server)
客户端——————————
1、从标准输入中读取用户输入;
2、把这个字符串通过socket传递给服务器;
3、尝试从服务器读取数据;
4、把从服务器读取到的数据显示到标准输出上。
服务器————————————
1、尝试从socket中读取数据(进行一系列的计算)
2、把这个字符串原封不动的写回给客户端。
UDP服务器
#include<stdio.h>
#include<unistd.h>
#include<sys/socket.h>
#include<arpa/inet.h>
//./server 192.168.80.132 9090
int main(int argc,char* argv[])
{
if(argc != 3)
{
printf("Usage ./server [ip] [port]\n");
return 1;
}
int fd = socket(AF_INET,SOCK_DGRAM,0);
if(fd < 0)
{
perror("socket");
return 1;
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(argv[1]);
addr.sin_port = htons(atoi(argv[2]));
int ret = bind(fd,(struct sockaddr*)&addr,sizeof(addr));
if(ret < 0)
{
perror("bind");
return 1;
}
while(1)
{
struct sockaddr_in peer;
socklen_t len = sizeof(peer);
char buf[1024] = {0};
ssize_t read_size = recvfrom(fd,buf,sizeof(buf) - 1,0,(struct sockaddr*)&peer,&len);
if(read_size < 0)
{
//filure
perror("recvfrom");
continue;
}
buf[read_size] = "\0";
printf("client say:%s\n",buf);
sendto(fd,buf,strlen(buf),0,(struct sockaddr*)&peer,len);
}
close(fd);
return 0;
}
*——socket的参数使用SOCK_DGRAM表示UDP;
*——bind之后就可以直接进行通信了;
*——使用sendto和recvfrom来进行数据读写。
UDP客户端
#include<stdio.h>
#include<sys/socket.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>
//.client 127.0.01 9090
int main(int argc,char *argv[])
{
if(argc != 3)
{
printf("usage /client[ip][port]\n");
return 1;
}
int fd=socket(AF_INET,SOCK_DGRAM,0);
if(fd<0){
perror("socket");
return 1 ;
}
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(argv[1]);
server_addr.sin_port = htons(atoi(argv[2]));
while(1)
{
char buf[1024]={0};
ssize_t read_size = read(0,buf,sizeof(buf)-1);
if(read_size<0){
perror("read");
return 1;
}
if(read_size==0){
printf("read done!\n");
return 0;
}
buf[read_size]='\0'
;
sendto(fd,buf,strlen(buf),0,(struct sockaddr*)&server_addr,sizeof(server_addr));
char buf_output[1024]={0};
read_size = recvfrom(fd,buf_output,sizeof(buf_output)-1,0,NULL,NULL);
if(read_size<0){
perror("recvfrom");
return 1;
}
buf_output[read_size]='\0';
printf("server resp:%s\n",buf_output);
}
close(fd);
return 0;
}
*——bind之后就可以直接进行通信了;
*——使用sendto和recvfrom来进行数据读写。
客户端一般不用绑定端口号:
由于客户端的机器装了哪些程序不确定,如果强行绑定端口号,就有可能和客户端的其他程序冲突,如果不绑定,操作系统就会在通信时自动分配一个端口号。