socket-(3)

TCP和UDP
TCP是 有连接协议(基于连接的协议),想要数据交互必须保持连接,会给服务器带来很大的压力。好处就是 可以重发一切错误数据,因此TCP的数据一定是正确和完整的。
UDP是 无连接协议,平时不保持任何的连接,服务器压力较小。缺点就是不会主动重发错误数据,因此有可能丢失数据。UDP也可以用connect()进行连接。
UDP编程
UDP编程:(socket(SOCK_DGRAM)就是UDP)
编程步骤:
1 创建socket(),type必须 SOCK_DGRAM
2 准备通信地址
3 如果Server,绑定bind,客户端什么都不用做。
4 使用 sendto()和recvfrom() 交互数据。
5 关闭socket。 close()
注:如果不想 拿发送方的通信地址,read()也可以接收。
int sendto(int sockfd,void* buf,size_t len,int flags,struct sockaddr* addr,socklen_t size)
前3个参数与write()一样,flags置0,后两个参数存储接收方的通信地址和地址长度。
成功返回 发送的字节数,失败 返回 -1.
ssize_t recvfrom(int sockfd,void* buf,
size_t len,int flags,struct sockaddr* addr,socklen_t* size)
前3个参数与read()一样,flags置0,后两个参数存发送方的通信地址和地址长度指针。
size 是 一个传入传出参数。
返回实际接收到的字节数,失败 -1.


例子:
例子1:
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
int main(){
int sockfd = socket(AF_INET,SOCK_DGRAM,0);
if(sockfd == -1) perror("socket"),exit(-1);
struct sockaddr_in addr;
addr.sin_family = AF_INET;//网络
addr.sin_port = htons(2222);//端口需要处理一下
addr.sin_addr.s_addr = //IP需要转换
inet_addr("192.168.182.2");
int res = bind(sockfd,
(struct sockaddr*)&addr,sizeof(addr));
if(res == -1) perror("bind"),exit(-1);
printf("bind ok ");
char buf[100] = {};
//int len = read(sockfd,buf,sizeof(buf));
struct sockaddr_in from;
socklen_t length = sizeof(from);
int len = recvfrom(sockfd,buf,sizeof(buf),0,
(struct sockaddr*)&from,&length);
printf("读到了%d字节,内容:%s ",len,buf);
sendto(sockfd,"welcome",7,0,
(struct sockaddr*)&from,sizeof(from));
close(sockfd);
}


例子2:
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
int main(){
int sockfd = socket(AF_INET,SOCK_DGRAM,0);
if(sockfd == -1) perror("socket"),exit(-1);
struct sockaddr_in addr;
addr.sin_family = AF_INET;//网络
addr.sin_port = htons(2222);//服务器的端口
addr.sin_addr.s_addr = //服务器的IP
inet_addr("192.168.182.2");
int res = sendto(sockfd,"hello",5,0,
(struct sockaddr*)&addr,sizeof(addr));
//write(sockfd,"hello",5);//无连接也能发才是UDP
printf("发送了%d字节 ",res);
char buf[100] = {};
read(sockfd,buf,sizeof(buf));
printf("buf=%s ",buf);
close(sockfd);
}

实例:
用UDP实现一个时间服务器。时间服务器就是取自己的系统时间,返回给客户端。
客户端先发请求(比如hello),服务器端返回当前系统时间,客户端再显示(年月日小时分秒格式)。
注:服务器端 要是一个 死循环,用信号退出
转换日期格式用:
秒差 time_t 函数time()获取
年月日小时分秒格式的时间 - struct tm
转换函数 - localtime()
例子:
#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<signal.h>
#include<string.h>
#include<time.h>

int sockfd;
void fa(int signo)
{
close(sockfd);
printf("time server is close! ");
exit(0);
}
int main()
{
signal(SIGINT,fa);
printf("按 CTIL+C 退出服务器! ");
sockfd = socket(AF_INET,SOCK_DGRAM,0);
if(sockfd == -1)
{
perror("socket"),exit(-1);
}
struct scokaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port= htons(2222);
addr.sin_addr.s_addr=INADDR_ANY;//INADDR_ANY 是跟本机交互的宏,如果跟其他机器交互,用inet_addr
int res = bind(sockfd,(struct sockaddr*)&addr,sizeof(addr));
if(res == -1)
{
perror("bind"),exit(-1);
}
printf("bind ok ");

while(1)
{
char buf[100]={};
struct sockaddr_in fmaddr;
socklen_t len = sizeof(fmaddr);
recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr*)&fmaddr,&len);
printf("客户端%s发送了请求 ",inet_ntoa(from.sin_addr));
time_t cur_time = time(0);
struct tm* cur = localtime(&cur_time);
sprintf(buf,"%4d-%02d-%02d %02d:%02d:%02d",
cur->tm_year+1900,
cur->tm_mon+1,
cur->tm_mday,
cur->tm_hour,
cur->tm_min,
cur->tm_sec);
sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*)&fmaddr,sizeof(fmaddr));
}

}
例子2:
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
int main(){
int sockfd = socket(AF_INET,SOCK_DGRAM,0);
if(sockfd == -1) perror("socket"),exit(-1);
struct sockaddr_in addr;
addr.sin_family = AF_INET;//网络
addr.sin_port = htons(2222);//服务器的端口
addr.sin_addr.s_addr = //服务器的IP
inet_addr("192.168.182.2");
int res = sendto(sockfd,"hello",5,0,
(struct sockaddr*)&addr,sizeof(addr));
//write(sockfd,"hello",5);//无连接也能发才是UDP
printf("发送了%d字节 ",res);
char buf[100] = {};
read(sockfd,buf,sizeof(buf));
printf("buf=%s ",buf);
close(sockfd);
}

原文地址:https://www.cnblogs.com/aiyq195/p/6433428.html