服务端:(提供服务的,一个服务端对于多个客户端)
1) 套接字------直接调用socket(将网络设备打开了)
2) bind(绑定)------给套接字设置端口号(主要是端口号的设置)与IP地址(本机是多少就是多少)
------(方便客户端连接)
3)recvfrom ------> 先处理客户的请求-------> sendto (循环)
客户端:(使用服务的)
1) 套接字
2)sendto <-------> recvfrom
3) 进程结束 ---- 套接字闭
server.c
1)socket
int socket(int domain, int type, int protocol);
功能:程序向内核提出创建一个基于内存的套接字描述符
参数:domain 地址族,PF_INET == AF_INET ==>互联网程序
PF_UNIX == AF_UNIX ==>单机程序
type 套接字类型:
SOCK_STREAM 流式套接字 ===》TCP
SOCK_DGRAM 用户数据报套接字===>UDP
SOCK_RAW 原始套接字 ===》IP
protocol 协议 ==》0 表示自动适应应用层协议。
返回值:成功 返回申请的套接字id
失败 -1;
typedef struct sockaddr * (SA);//重要墙砖类型,addr_in
用户数据报: int type;
SOCK_STREAM(TCP);
SOCK_DGRAM(UDP);
int protocol ;//确定是UDP 的套接字 =0;
int sockfd=socket(AF_INET,SOCK_DGRAM,0);
if(sockfd==-1)
{
perror("socket");
exit(1);
}
2)bind;
2、int bind(int sockfd, struct sockaddr *my_addr,
socklen_t addrlen);
功能:如果该函数在服务器端调用,则表示将参数1相关
的文件描述符文件与参数2 指定的接口地址关联,
用于从该接口接受数据。
如果该函数在客户端调用,则表示要将数据从
参数1所在的描述符中取出并从参数2所在的接口
设备上发送出去。
注意:如果是客户端,则该函数可以省略,由默认
接口发送数据。
参数:sockfd 之前通过socket函数创建的文件描述符,套接字id
my_addr 是物理接口的结构体指针。表示该接口的信息。
struct sockaddr 通用地址结构
{
u_short sa_family; 地址族
char sa_data[14]; 地址信息
};
转换成网络地址结构如下:
struct _sockaddr_in ///网络地址结构
{
u_short sin_family; 地址族
u_short sin_port; ///地址端口
struct in_addr sin_addr; ///地址IP
char sin_zero[8]; 占位
};
struct in_addr
{
in_addr_t s_addr;
}
//man 7 ip; 我们所需要的地址结构体
struct socketaddr_in ser,cli;//定义互联网结构体 两个变量一个用于客户端一个用于服务端
bzero(&ser,sizeof(ser));//清空结构体
bzero(&cli,sizeof(cli));
struct socketaddr_in;
ser.sin_family=AF_INET;
ser.sin_port=htones(50000);//大小断转化host to net short
ser.sin_addr.s_addr=inet_addr("自己的ip地址");
int ret = bind(sockfd,&ser,sizeof(ser));
if( ret == -1)
{
perror("bind");
exit(1);
}
3)开始收发
while(1)
{
char buf[512]={0};
socklen_t len=sizof(cli);
recvfrom(sockfd,buf,sizeof(buf),&cli,&len);
time_t tm;
time(&tm);
sprintf(buf,"%s %s",buf,ctime(&tm));
sendto(sockfd,buf,strlen(buf),0,&cli,len);
}
close(sockfd);
recvfrom(从那收sockfd,收到哪buf,本次接收的最大长度sizeof(buf) , 接受方式 默认为0 ,发送方 &cli , &len)
sendto(从哪发网络设备发sockfd , 发谁buf , 发多大strlen(buf) , 0 发送方式默认方式(要么收到要么丢失), 发到哪&cli , len );
ifconfig(得到自己的地址)
完整代码
server.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
typedef struct sockaddr * (SA);
int main(int argc, char *argv[])
{
int sockfd = socket(AF_INET,SOCK_DGRAM,0);
if(-1 == sockfd)
{
perror("socket");
exit(1);
}
// man 7 ip
struct sockaddr_in ser,cli;
bzero(&ser,sizeof(ser));
bzero(&cli,sizeof(cli));
ser.sin_family = AF_INET;
// 大小端转化 host to net short
ser.sin_port = htons(50000);
ser.sin_addr.s_addr = inet_addr("192.168.203.128");
int ret = bind(sockfd,(SA)&ser,sizeof(ser));
if(-1 == ret)
{
perror("bind");
exit(1);
}
socklen_t len = sizeof(cli);
while(1)
{
char buf[512]={0};
recvfrom(sockfd,buf,sizeof(buf),0,(SA)&cli,&len);
time_t tm;
time(&tm);
sprintf(buf,"%s %s",buf,ctime(&tm));
sendto(sockfd,buf,strlen(buf),0,(SA)&cli,len);
}
close(sockfd);
return 0;
}
client.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
typedef struct sockaddr * (SA);
int main(int argc, char *argv[])
{
int sockfd = socket(AF_INET,SOCK_DGRAM,0);
if(-1 == sockfd)
{
perror("socket");
exit(1);
}
struct sockaddr_in ser;
bzero(&ser,sizeof(ser));
ser.sin_family = AF_INET;
// 大小端转化 host to net short
ser.sin_port = htons(50000);
ser.sin_addr.s_addr = inet_addr("192.168.203.128");
while(1)
{
char buf[512]="hello,this is udp test";
sendto(sockfd,buf,strlen(buf),0,(SA)&ser,sizeof(ser));
bzero(buf,sizeof(buf));
recvfrom(sockfd,buf,sizeof(buf),0,NULL,NULL);
printf("buf is %s\n",buf);
sleep(1);
}
close(sockfd);
return 0;
}