UDP特点:
1.不安全不可靠的传输方式
2.UDP资源开销小,实现机制简单
3.UDP是无连接的(面向数据包)
TCP:
发送端:
1.创建用来通信的套接字(socket)
2.发送连接请求(connect)
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 功能: 向接收方发起连接请求 参数: sockfd:套接字文件描述符 addr:接收方的IP地址和端口号 addrlen:接收方的IP地址和端口号的大小 返回值: 成功返回0 失败返回-1 |
3.发送数据(send)
ssize_t send(int sockfd, const void *buf, size_t len, int flags); 功能: 向接收方发送数据 参数: sockfd:套接字文件描述符 buf:要发送的数据的首地址 len:要发送的数据的长度 flags:标志位 返回值: 成功返回发送字节数 失败返回-1 |
4.接收数据(recv)
ssize_t recv(int sockfd, void *buf, size_t len, int flags); 功能: 接收发送方发送的数据 参数: sockfd:套接字文件描述符 buf:接收数据的缓冲区首地址 len:接收数据的缓冲区的大小 flags:标志位 返回值: 成功返回实际接收字节数 失败返回-1 对方关闭返回0 |
5.关闭(close)
接收端:
1.创建套接字(socket)
2.绑定IP地址和端口号(bind)
3.监听(listen)
int listen(int sockfd, int backlog); 功能: 监听发送三次握手连接的套接字,并放入等到处理队列中 参数: sockfd:套接字文件描述符 backlog:等待队列的大小(最多存放尚未被处理的三次握手请求的个数) 返回值: 成功返回0 失败返回-1 |
4.处理连接请求(accept)
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); 功能: 处理等待队列中的第一个套接字 参数: sockfd:套接字文件描述符 addr:存放发送方IP地址的空间首地址 addrlen:存放发送方IP地址的空间大小 返回值: 成功返回一个新的文件描述符 失败返回-1 |
5.收发(同上)
6.关闭
练习:
练习:使用TCP实现全双工聊天(线程实现)
send.c
#include "../head.h"
pthread_t tid1;
pthread_t tid2;
int sockfd = 0;
void *threadfun1(void *arg){
char tmpbuff[1024] = {0};
ssize_t nsize = 0;
ssize_t nret = 0;
while(1){
memset(tmpbuff,0,sizeof(tmpbuff));
fgets(tmpbuff,sizeof(tmpbuff),stdin);
tmpbuff[strlen(tmpbuff)-1] = '\0';
nsize = send(sockfd,tmpbuff,strlen(tmpbuff),0);
if(-1 == nsize){
perror("fail to send");
return NULL;
}
if(!strcmp(tmpbuff,"quit")){
break;
}
}
pthread_cancel(tid2);
return NULL;
}
void *threadfun2(void *arg){
char tmpbuff[1024] = {0};
ssize_t nsize = 0;
ssize_t nret = 0;
while(1){
memset(tmpbuff,0,sizeof(tmpbuff));
nsize = recv(sockfd,tmpbuff,sizeof(tmpbuff),0);
if(-1 == nsize){
perror("fail to send");
return NULL;
}
if(!strcmp(tmpbuff,"quit")){
break;
}
printf("SEND:%s\n",tmpbuff);
}
pthread_cancel(tid1);
return NULL;
}
int main(void){
struct sockaddr_in recvaddr;
int ret = 0;
ssize_t nsize = 0;
sockfd = socket(AF_INET,SOCK_STREAM,0);
if( -1 == sockfd){
perror("fali to socket");
return -1;
}
recvaddr.sin_family = AF_INET;
recvaddr.sin_port = htons(RECV_PORT);
recvaddr.sin_addr.s_addr = inet_addr(RECV_IP);
ret = connect(sockfd,(struct sockaddr *)&recvaddr,sizeof(recvaddr));
if(-1 == ret){
perror("fail to connect");
return -1;
}
pthread_create(&tid1,NULL,threadfun1,NULL);
pthread_create(&tid2,NULL,threadfun2,NULL);
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
close(sockfd);
return 0;
}
recv.c
#include "../head.h"
pthread_t tid1;
pthread_t tid2;
int confd = 0;
void *threadfun1(void *arg){
char tmpbuff[1024] = {0};
ssize_t nsize = 0;
while(1){
memset(tmpbuff,0,sizeof(tmpbuff));
fgets(tmpbuff,sizeof(tmpbuff),stdin);
tmpbuff[strlen(tmpbuff)-1] = '\0';
nsize = send(confd,tmpbuff,strlen(tmpbuff),0);
if(-1 == nsize){
perror("fail to send");
return NULL;
}
if(!strcmp(tmpbuff,"quit")){
break;
}
}
pthread_cancel(tid2);
return NULL;
}
void *threadfun2(void *arg){
char tmpbuff[1024] = {0};
ssize_t nsize = 0;
ssize_t nret = 0;
while(1){
memset(tmpbuff,0,sizeof(tmpbuff));
nsize = recv(confd,tmpbuff,sizeof(tmpbuff),0);
if(-1 == nsize){
perror("fail to send");
return NULL;
}
if(!strcmp(tmpbuff,"quit")){
break;
}
printf("RECV:%s\n",tmpbuff);
}
pthread_cancel(tid1);
return NULL;
}
int main(void){
int sockfd = 0;
struct sockaddr_in recvaddr;
struct sockaddr_in sendaddr;
socklen_t len = sizeof(sendaddr);
int ret = 0;
sockfd = socket(AF_INET,SOCK_STREAM,0);
if( -1 == sockfd){
perror("fali to socket");
return -1;
}
recvaddr.sin_family = AF_INET;
recvaddr.sin_port = htons(RECV_PORT);
recvaddr.sin_addr.s_addr = inet_addr(RECV_IP);
ret = bind(sockfd,(struct sockaddr *)&recvaddr,sizeof(recvaddr));
if(-1 == ret){
perror("fail to bind");
return -1;
}
ret = listen(sockfd,10);
if(-1 == ret){
perror("fail to listen");
return -1;
}
confd = accept(sockfd,(struct sockaddr*)&sendaddr,&len);
if(-1 == ret){
perror("fail to accept");
return -1;
}
pthread_create(&tid1,NULL,threadfun1,NULL);
pthread_create(&tid2,NULL,threadfun2,NULL);
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
close(confd);
close(sockfd);
return 0;
}
练习:使用UDP完成聊天室功能(进程实现)
send.c
#include "../head.h"
int main(void){
int sockfd = 0;
struct sockaddr_in recvaddr;
char tmpbuff[1024] = {0};
ssize_t nszie = 0;
pid_t pid = 0;
sockfd = socket(AF_INET,SOCK_DGRAM,0);
if(-1 == sockfd){
perror("fail to socket");
return -1;
}
recvaddr.sin_family = AF_INET;
recvaddr.sin_port = htons(RECV_PORT);
recvaddr.sin_addr.s_addr = inet_addr(RECV_IP);
nszie = sendto(sockfd,"a",2,0,(struct sockaddr *)&recvaddr,sizeof(recvaddr));
if(-1 == nszie){
perror("fail to sendto");
return -1;
}
pid = fork();
if(-1 == pid){
perror("fail to fork");
return -1;
}
if(pid == 0){
while (1)
{
memset(tmpbuff,0,sizeof(tmpbuff));
fgets(tmpbuff,sizeof(tmpbuff),stdin);
tmpbuff[strlen(tmpbuff)-1] = '\0';
nszie = sendto(sockfd,tmpbuff,strlen(tmpbuff),0,(struct sockaddr *)&recvaddr,sizeof(recvaddr));
if(-1 == nszie){
perror("fail to sendto");
return -1;
}
if(strcmp(tmpbuff,"quit") ==0){
break;
}
}
kill(getppid(),SIGKILL);
}else if(pid > 0){
while(1){
memset(tmpbuff,0,sizeof(tmpbuff));
nszie = recvfrom(sockfd,tmpbuff,sizeof(tmpbuff),0,NULL,NULL);
if(-1 == nszie){
perror("fail to recvfrom");
return -1;
}
if(strcmp(tmpbuff,"quit")== 0){
break;
}
printf("%s:%d->%s\n",inet_ntoa(recvaddr.sin_addr),ntohs(recvaddr.sin_port),tmpbuff);
}
kill(pid,SIGKILL);
}
close(sockfd);
return 0;
}
recv.c
#include "../head.h"
int main(void){
int sockfd = 0;
struct sockaddr_in recvaddr;
struct sockaddr_in sendaddr;
char tmpbuff[1024] = {0};
ssize_t nszie = 0;
pid_t pid = 0;
int ret = 0;
socklen_t addlen = sizeof(sendaddr);
sockfd = socket(AF_INET,SOCK_DGRAM,0);
if(-1 == sockfd){
perror("fail to socket");
return -1;
}
recvaddr.sin_family = AF_INET;
recvaddr.sin_port = htons(RECV_PORT);
recvaddr.sin_addr.s_addr = inet_addr(RECV_IP);
ret = bind(sockfd,(struct sockaddr*)&recvaddr,sizeof(recvaddr));
if (-1 == ret)
{
perror("fail to bind");
return -1;
}
nszie = recvfrom(sockfd,tmpbuff,sizeof(recvaddr),0,(struct sockaddr *)&sendaddr,&addlen);
if(-1 == nszie){
perror("fail to sendto");
return -1;
}
printf("%s:%d->%s\n",inet_ntoa(sendaddr.sin_addr),ntohs(sendaddr.sin_port),tmpbuff);
pid = fork();
if(-1 == pid){
perror("fail to fork");
return -1;
}
if(pid == 0){
while(1){
memset(tmpbuff,0,sizeof(tmpbuff));
fgets(tmpbuff,sizeof(tmpbuff),stdin);
tmpbuff[strlen(tmpbuff)-1] = '\0';
nszie = sendto(sockfd,tmpbuff,strlen(tmpbuff),0,(struct sockaddr *)&sendaddr,sizeof(sendaddr));
if(-1 == nszie){
perror("fail to sendto");
return -1;
}
if(strcmp(tmpbuff,"quit") == 0){
break;
}
}
kill(getppid(),SIGKILL);
}else if(pid > 0){
while(1){
memset(tmpbuff,0,sizeof(tmpbuff));
nszie = recvfrom(sockfd,tmpbuff,sizeof(tmpbuff),0,NULL,NULL);
if(-1 == nszie){
perror("fail to recvfrom");
return -1;
}
if(strcmp(tmpbuff,"quit") == 0){
break;
}
printf("%s:%d->%s\n",inet_ntoa(sendaddr.sin_addr),ntohs(sendaddr.sin_port),tmpbuff);
}
kill(pid,SIGKILL);
}
close(sockfd);
return 0;
}