TCP:
服务器端:
1、创建一个socket,int listenfd=socket() ;
2、设置socket属性,用函数setsockopt(); * 可选
3、绑定IP地址、端口等信息到socket上,用函数bind();
4、开启监听,用函数listen(listenfd,size);
(内核启动监听,接收客户端连接,不会阻塞)
5、接收客户端上来的连接,int c=accept();
(获取一个连接完成的客户端,具体与服务器连接上的客户端)
6、收发数据,用函数send()和recv(),或者read()和write();
7、关闭网络连接; close(c)
8、关闭监听; close(listenfd)
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<string.h>
#include<signal.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
int listenfd=-1;
void sigfun(int sign)
{
close(listenfd);
exit(0);
}
int main()
{
signal(SIGINT,sigfun);
int listenfd=socket(AF_INET,SOCK_STREAM,0);//函数功能:创建一个socket
assert(listenfd!=-1);
struct sockaddr_in ser,cli;
memset(&ser,0,sizeof(ser));//初始化0
ser.sin_family=AF_INET;//地址簇 PF-INET 协议簇
ser.sin_port=htons(6000);//主机小端模式转化为网络的大端模式
ser.sin_addr.s_addr=inet_addr("127.0.0.1");//ip地址 地址转换函数in_addr_t inet_addr(const char*strptr)
int res=bind(listenfd,(struct sockaddr *)&ser,sizeof(ser));
assert(res!=-1);//绑定失败 1 ip地址不对 2 端口号被占用 没有权限使用
listen(listenfd,5);//启动监听 socket返回的值监听这个套接字
while(1)//服务器接收不同客户端链接的循环
{
int clilen=sizeof(cli);
int c=accept(listenfd,(struct sockaddr*)&cli,&clilen);//有人链接才会返回,否则阻塞
assert(c!=-1);
while(1)//与一个客户端交互的循环
{
char buff[128]={0};
int n=recv(c,buff,127,0);//从哪个客户端 获取的数据 阻塞运行,会等
//recv返回 函数调用本身出错/ 客户端关闭
if(n<=0)
{
printf("one client unlink\n");
// close(c);
break;
}
printf("%d: %s\n",c,buff);
send(c,"ok",2,0); //发送数据,将数据发送给谁
}
close(c);
}
close(listenfd);
return 0;
}
客户端:
1、创建一个socket,int sockfd=socket();
2、设置socket属性,用函数setsockopt();* 可选
3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选
(如果没有绑定,内核会自动选择一个可用端口,自动探测本地的IP地址)
4、设置要连接的对方的IP地址和端口等属性;
5、连接服务器,用函数connect(),即发起连接;
6、收发数据,用函数send()和recv(),或者read()和write();
7、关闭网络连接;close(sockfd)
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<netinet/in.h>
int main()
{
int sockfd=socket(AF_INET,SOCK_STREAM,0);
assert(sockfd!=-1);
struct sockaddr_in ser;
memset(&ser,0,sizeof(ser));
ser.sin_family=AF_INET;
ser.sin_port=htons(6000);
ser.sin_addr.s_addr=inet_addr("127.0.0.1");
// 发起链接 和哪个服务器进行链接
int res=connect(sockfd,(struct sockaddr*)&ser,sizeof(ser));
assert(res!=-1);
while(1)
{
printf("please input:");
fflush(stdout);
char buff[128]={0};
fgets(buff,128,stdin);
// buff[strlen(buff)-1]=0;
if(strncmp(buff,"end",3)==0)
{
// close(sockfd);
break;
}
send(sockfd,buff,strlen(buff)-1,0);//客户端先send 服务器那块recv
char recvbuff[128]={0};
int n=recv(sockfd,recvbuff,127,0);
if(n<=0)
{
// close(sockfd);
break;
}
printf("%s\n",recvbuff);
}
close(sockfd);
return 0;
}
UDP:
服务器端:
1、创建一个socket,int sockfd=socket();
2、设置socket属性,用函数setsockopt();* 可选
3、绑定IP地址、端口等信息到socket上,用函数bind();
4、循环接收数据,用函数recvfrom(); //sendto
5、关闭网络连接; close(sockfd)
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
int main()
{
int sockfd=socket(AF_INET,SOCK_DGRAM,0);//创建socket对象
//使用ipv4地址通信 数据报协议
assert(sockfd!=-1);
struct sockaddr_in ser,cli;
memset(&ser,0,sizeof(ser));//初始化
ser.sin_family=AF_INET;//通信地址类型
ser.sin_addr.s_addr=inet_addr("127.0.0.1");//点分十进制转化为无符号整型
ser.sin_port=htons(6500);//获取端口号 主机字节序转化为网络字节序
//bind函数 把socket对象与通信地址建立联系
int res=bind(sockfd,(struct sockaddr*)&ser,sizeof(ser));
//struct sockaddr* addr指定了想要绑定的ip和端口号
assert(res!=-1);
/*不需要 listen */
while(1)
{
char buff[128]={0};
int cli_len=sizeof(cli);
int n=recvfrom(sockfd,buff,127,0,(struct sockaddr*)&cli,&cli_len);
// buff 缓冲区 127 缓冲区大小 标记位 通常为0 数据来源端的地址
if(n==-1)
{
close(sockfd);
break;
}
unsigned short cli_port=ntohs(cli.sin_port);
//功能:把16位网络字节序转换成16位的主机字节序
char *cli_ip=inet_ntoa(cli.sin_addr);
printf("%s:%u %s\n",cli_ip,cli_port,buff);
sendto(sockfd,"ok",2,0,(struct sockaddr*)&cli,sizeof(cli));
// 0 标记位 数据要发送的目标地址
}
close(sockfd);
return 0;
}
客户端:
1、创建一个socket,int sockfd=socket();
2、设置socket属性,用函数setsockopt();* 可选
3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选
4、设置对方的IP地址和端口等属性;
5、发送数据,用函数sendto(); //sendto
6、关闭网络连接;close(sockfd)
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
int main()
{
int sockfd=socket(AF_INET,SOCK_DGRAM,0);//创建socket对象
//使用ipv4地址通信 数据报协议
assert(sockfd!=-1);
struct sockaddr_in ser,cli;
memset(&ser,0,sizeof(ser));//初始化
ser.sin_family=AF_INET;//通信地址类型
ser.sin_addr.s_addr=inet_addr("127.0.0.1");//点分十进制转化为无符号整型
ser.sin_port=htons(6500);//获取端口号 主机字节序转化为网络字节序
//bind函数 把socket对象与通信地址建立联系
int res=bind(sockfd,(struct sockaddr*)&ser,sizeof(ser));
//struct sockaddr* addr指定了想要绑定的ip和端口号
assert(res!=-1);
/*不需要 listen */
while(1)
{
char buff[128]={0};
int cli_len=sizeof(cli);
int n=recvfrom(sockfd,buff,127,0,(struct sockaddr*)&cli,&cli_len);
// buff 缓冲区 127 缓冲区大小 标记位 通常为0 数据来源端的地址
if(n==-1)
{
close(sockfd);
break;
}
/*
if(n<=0)
{
printf("recv error\n");
}*/
unsigned short cli_port=ntohs(cli.sin_port);
//功能:把16位网络字节序转换成16位的主机字节序
char *cli_ip=inet_ntoa(cli.sin_addr);
printf("%s:%u %s\n",cli_ip,cli_port,buff);
sendto(sockfd,"ok",2,0,(struct sockaddr*)&cli,sizeof(cli));
// 0 标记位 数据要发送的目标地址
}
close(sockfd);
return 0;
}
TCP和UDP是OSI模型中的运输层中的协议。
TCP提供可靠的通信传输,而UDP则常被用于让广播和细节控制交给应用的通信传输。