我要成为嵌入式高手之3月7日Linux高编第十七天!!
————————————————————————————
回顾
重要程序
1、UDP实现文件的发送
发端:
#include "head.h"
int main(void)
{
int sockfd = 0;
struct sockaddr_in recvaddr;
ssize_t nsize = 0;
int ret = 0;
int fd = 0;
char pathname[1024] = {0};
char tmpbuff[1024] = {0};
ssize_t nret;
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(33333);
recvaddr.sin_addr.s_addr = inet_addr("192.168.1.167");
memset(pathname, 0, sizeof(pathname));
gets(pathname);
nsize = sendto(sockfd, pathname, strlen(pathname), 0, (struct sockaddr *)&recvaddr, sizeof(recvaddr));
if (nsize == -1)
{
perror("fail to sendto");
return -1;
}
fd = open(pathname, O_RDONLY);
if (fd == -1)
{
perror("fail to open");
return -1;
}
printf("pathname: %s\n", pathname);
while (1)
{
usleep(10);
nret = read(fd, tmpbuff, sizeof(tmpbuff));
nsize = sendto(sockfd, tmpbuff, nret, 0, (struct sockaddr *)&recvaddr, sizeof(recvaddr));
if (nsize == -1)
{
perror("fail to sendto tmpbuff");
return -1;
}
if (nret <= 0)
{
break;
}
}
sprintf(tmpbuff, "|__quit__|");
nsize = sendto(sockfd, tmpbuff, strlen(tmpbuff)+1, 0, (struct sockaddr *)&recvaddr, sizeof(recvaddr));
if (nsize == -1)
{
perror("fail to sendto tmpbuff");
return -1;
}
printf("成功发送 %s 文件\n", pathname);
close(fd);
close(sockfd);
return 0;
}
收端:
#include "head.h"
int main(void)
{
int ret = 0;
int sockfd = 0;
char tmpbuff[4096] = {0};
struct sockaddr_in recvaddr;
ssize_t nsize = 0;
struct sockaddr_in sendaddr;
socklen_t len = sizeof(sendaddr);
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1)
{
perror("fail to socket");
return -1;
}
recvaddr.sin_family = AF_INET;
recvaddr.sin_port = htons(33333);
recvaddr.sin_addr.s_addr = inet_addr("192.168.1.167");
ret = bind(sockfd, (struct sockaddr *)&recvaddr, sizeof(recvaddr));
if (ret == -1)
{
perror("fail to bind");
return -1;
}
nsize = recvfrom(sockfd, tmpbuff, sizeof(tmpbuff), 0, (struct sockaddr *)&sendaddr, &len);
if (nsize == -1)
{
perror("fail to recvfrom");
return -1;
}
// printf("%s:%d>>接受到%ld个字节:%s\n",inet_ntoa(sendaddr.sin_addr),ntohs(sendaddr.sin_port),nsize,tmpbuff);
int fd = 0;
char ch[1024]= {0};
fd = open(tmpbuff,O_WRONLY | O_CREAT | O_TRUNC, 0664);
if (fd == -1)
{
perror("fail to fopen");
return -1;
}
while(nsize != 0)
{
memset(ch, 0, sizeof(ch));
nsize = recvfrom(sockfd, ch, sizeof(ch), 0, (struct sockaddr *)&sendaddr, &len);
if (nsize == -1)
{
perror("fail to recvfrom");
return -1;
}
if (!strcmp(ch,"1"))
{
break;
}
write(fd,ch,nsize);
printf("写入%ld字节\n",nsize);
}
printf("接受完成!\n");
close(fd);
close(sockfd);
return 0;
}
2、UDP实现全双工的聊天
发送端
#include "head.h"
char name[32] = {0};
int sockfd = 0;
struct sockaddr_in recvaddr;
pthread_t tid_send;
pthread_t tid_recv;
void *sendfun(void *arg)
{
ssize_t nsize = 0;
struct msgbuf sendmsg;
while(1)
{
memset(&sendmsg, 0, sizeof(sendmsg));
sendmsg.type = MSG_TYPE_CHAT;
sprintf(sendmsg.name, "%s", name);
gets(sendmsg.text);
if (!strcmp(sendmsg.text, ".quit"))
{
sendmsg.type = MSG_TYPE_END;
}
nsize = sendto(sockfd, &sendmsg, sizeof(sendmsg), 0, (struct sockaddr *)&recvaddr, sizeof(recvaddr));
if (nsize == -1)
{
perror("fail to sendto");
return NULL;
}
if (sendmsg.type == MSG_TYPE_END)
{
break;
}
}
pthread_cancel(tid_recv);
return NULL;
}
void *recvfun(void *arg)
{
struct msgbuf recvmsg;
ssize_t nsize = 0;
while(1)
{
memset(&recvmsg, 0, sizeof(recvmsg));
nsize = recvfrom(sockfd, &recvmsg, sizeof(recvmsg), 0, NULL, NULL);
if (-1 == nsize)
{
perror("fail to recvfrom");
return NULL;
}
if (recvmsg.type == MSG_TYPE_CHAT)
{
printf("%s(%s:%d)>%s\n", recvmsg.name, RECV_ADDR, RECV_PORT, recvmsg.text);
}
else if (recvmsg.type == MSG_TYPE_END)
{
break;
}
}
pthread_cancel(tid_send);
return NULL;
}
int main(void)
{
ssize_t nsize = 0;
struct msgbuf sendmsg;
/*设置接收方信息*/
recvaddr.sin_family = AF_INET;
recvaddr.sin_port = htons(RECV_PORT);
recvaddr.sin_addr.s_addr = inet_addr(RECV_ADDR);
/*输入昵称*/
printf("请输入您的昵称:\n");
gets(name);
/*创建套接字*/
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1)
{
perror("fail to sockfd");
return -1;
}
/*设置要发送的信息*/
memset(&sendmsg, 0, sizeof(sendmsg));
sendmsg.type = MSG_TYPE_START;
sprintf(sendmsg.name, "%s", name);
/*发送信息*/
nsize = sendto(sockfd, &sendmsg, sizeof(sendmsg), 0, (struct sockaddr *)&recvaddr, sizeof(recvaddr));
if (nsize == -1)
{
perror("fail to sendto");
return -1;
}
pthread_create(&tid_send, NULL, sendfun, NULL);
pthread_create(&tid_recv, NULL, recvfun, NULL);
pthread_join(tid_send, NULL);
pthread_join(tid_recv, NULL);
close(sockfd);
return 0;
}
接收端
#include "head.h"
char name[32] = {0};
int sockfd = 0;
struct sockaddr_in recvaddr;
struct sockaddr_in sendaddr;
pthread_t tid_send;
pthread_t tid_recv;
void *sendfun(void *arg)
{
ssize_t nsize = 0;
struct msgbuf sendmsg;
while(1)
{
memset(&sendmsg, 0, sizeof(sendmsg));
sendmsg.type = MSG_TYPE_CHAT;
sprintf(sendmsg.name, "%s", name);
gets(sendmsg.text);
if (!strcmp(sendmsg.text, ".quit"))
{
sendmsg.type = MSG_TYPE_END;
}
nsize = sendto(sockfd, &sendmsg, sizeof(sendmsg), 0, (struct sockaddr *)&sendaddr, sizeof(sendaddr));
if (nsize == -1)
{
perror("fail to sendto");
return NULL;
}
if (sendmsg.type == MSG_TYPE_END)
{
break;
}
}
pthread_cancel(tid_recv);
return NULL;
}
void *recvfun(void *arg)
{
struct msgbuf recvmsg;
ssize_t nsize = 0;
while(1)
{
memset(&recvmsg, 0, sizeof(recvmsg));
nsize = recvfrom(sockfd, &recvmsg, sizeof(recvmsg), 0, NULL, NULL);
if (-1 == nsize)
{
perror("fail to recvfrom");
return NULL;
}
if (recvmsg.type == MSG_TYPE_CHAT)
{
printf("%s(%s:%d)>%s\n", recvmsg.name, inet_ntoa(sendaddr.sin_addr), ntohs(sendaddr.sin_port), recvmsg.text);
}
else if (recvmsg.type == MSG_TYPE_END)
{
break;
}
}
pthread_cancel(tid_send);
return NULL;
}
int main(void)
{
char tmpbuff[1024] = {0};
struct msgbuf recvmsg;
int ret = 0;
socklen_t addrlen = sizeof(sendaddr);
/*设置接收方信息*/
recvaddr.sin_family = AF_INET;
recvaddr.sin_port = htons(RECV_PORT);
recvaddr.sin_addr.s_addr = inet_addr(RECV_ADDR);
/*输入昵称*/
printf("请输入您的昵称:\n");
gets(name);
/*创建套接字*/
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1)
{
perror("fail to sockfd");
return -1;
}
ret = bind(sockfd, (struct sockaddr *)&recvaddr, sizeof(recvaddr));
if (-1 == ret)
{
perror("fail to bind");
return -1;
}
/*设置要发送的信息*/
memset(&recvmsg, 0, sizeof(recvmsg));
/*接收信息*/
ret = recvfrom(sockfd, &recvmsg, sizeof(recvmsg), 0, (struct sockaddr *)&sendaddr, &addrlen);
if (ret == -1)
{
perror("fail to recvfrom");
return -1;
}
pthread_create(&tid_send, NULL, sendfun, NULL);
pthread_create(&tid_recv, NULL, recvfun, NULL);
pthread_join(tid_recv, NULL);
pthread_join(tid_send, NULL);
close(sockfd);
return 0;
}
head.h
#ifndef _HEAD_H
#define _HEAD_H
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <time.h>
#include <pwd.h>
#include <stdlib.h>
#include <grp.h>
#include <sys/wait.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <arpa/inet.h>
struct msgbuf
{
int type; //消息类型
char name[32]; //昵称
char text[32]; //消息
};
#define MSG_TYPE_START 100 //开始聊天消息类型
#define MSG_TYPE_END 200 //退出聊天消息类型
#define MSG_TYPE_CHAT 300 //聊天消息类型
#define RECV_ADDR "192.168.1.172" //接收端地址
#define RECV_PORT 50000 //接收端端口
#endif
学习笔记
TCP通信
TCP发端(客户端)
socket -> connect -> send / recv-> close
TCP收端(服务端)
socket -> bind -> listen -> accept -> send / recv -> close
1、connect
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
功能:发起链接请求
参数:
sockfd:套接字的描述符
addr:目的地址存放空间首地址
addrlen:IP地址的大小
返回值:成功0,失败-1;
2、send
#include <sys/types.h>
#include <sys/socket.h>
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
功能:发送数据
参数:
sockfd:套接字描述符
buf:发送数据空间的首地址
len:发送数据的长度
flags:属性默认为0
返回值:
成功返回实际发送字节数
失败返回-1;
3、recv
#include <sys/types.h>
#include <sys/socket.h>
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
功能:接收数据
参数:
sockfd:套接字描述符
buf:存放数据空间首地址
len:最大接收数据的长度
flags:属性默认0
返回值:
成功返回实际接收字节数,失败返回-1;
若对方退出,返回0
客户端:
#include "head.h"
int main(void)
{
int ret = 0;
int sockfd = 0;
struct sockaddr_in serveaddr;
char tmpbuff[1024] = {0};
ssize_t nsize = 0;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == sockfd)
{
perror("fail to socket");
return -1;
}
serveaddr.sin_family = AF_INET;
serveaddr.sin_port = htons(50000);
serveaddr.sin_addr.s_addr = inet_addr("192.168.1.101");
ret = connect(sockfd, (struct sockaddr *)&serveaddr, sizeof(serveaddr));
if (ret == -1)
{
perror("fail to connect");
return -1;
}
gets(tmpbuff);
nsize = send(sockfd, tmpbuff, strlen(tmpbuff), 0);
if (nsize == -1)
{
perror("fail to send");
return -1;
}
memset(tmpbuff, 0, sizeof(tmpbuff));
nsize = recv(sockfd, tmpbuff, sizeof(tmpbuff), 0);
if (nsize == -1)
{
perror("fail to recv");
return -1;
}
printf("RECV: %s\n", tmpbuff);
close(sockfd);
return 0;
}
4、listen
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int listen(int sockfd, int backlog);
功能:监听客户端发送的链接请求,不会阻塞
参数:
sockfd:套接字描述符
backlog:允许等待的尚未被处理的三次握手请求的最大个数
返回值:成功0,失败-1;
5、accept
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
功能:
处理等待链接队列中的第一个链接请求,若没有人发送链接请求会阻塞等待,直到有连接请求
参数:
sockfd:套接字描述符
addr:存放IP地址的空间首地址
addrlen:存放IP地址大小空间首地址
返回值:
成功返回一个新的文件描述符
失败返回-1;
服务端:
#include "head.h"
int main(void)
{
int sockfd = 0;
struct sockaddr_in serveaddr;
int ret = 0;
int confd = 0;
ssize_t nsize = 0;
char tmpbuff[1024] = {0};
serveaddr.sin_family = AF_INET;
serveaddr.sin_port = htons(50000);
serveaddr.sin_addr.s_addr = INADDR_ANY;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
{
perror("fail to socket");
return -1;
}
ret = bind(sockfd, (struct sockaddr *)&serveaddr, sizeof(serveaddr));
if (ret == -1)
{
perror("fail to bind");
return -1;
}
ret = listen(sockfd, 10);
if (-1 == ret)
{
perror("fail to listen");
return -1;
}
confd = accept(sockfd, NULL, NULL);
if (-1 == confd)
{
perror("fail to accept");
return -1;
}
nsize = recv(confd, tmpbuff, sizeof(tmpbuff), 0);
if (-1 == nsize)
{
perror("fail to recv");
return -1;
}
printf("RECV: %s\n", tmpbuff);
memset(tmpbuff, 0, sizeof(tmpbuff));
gets(tmpbuff);
nsize = send(confd, tmpbuff, strlen(tmpbuff), 0);
if (-1 == nsize)
{
perror("fail to send");
return -1;
}
close(confd);
close(sockfd);
return 0;
}