进程
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
void fun(int a,int b)
{
printf("china\n");
printf("a+b=%d",a+b);
exit(0);//不刷新缓冲区,结束进程
return;
}
int main(int argc, char const *argv[])
{
//创建父子进程
pid_t pid = fork();
if(pid < 0)
{
printf("fork err");
return -1;
}
else if(pid == 0)//返回0是子进程
{
printf("hello\n");
fun(3,4);
sleep(1);
printf("hahahaha\n");
}
else//否则一率是父进程
{
printf("world\n");
waitpid(pid,NULL,0);//阻塞回收指定子进程
printf("ni hao\n");
}
return 0;
}
线程
#include <stdio.h>
#include <pthread.h>
void *handler(void *arg)
{
printf("in pthread\n");
return NULL;
}
int main(int argc, char const *argv[])
{
pthread_t tid;
//创建线程
if(pthread_create(&tid,NULL,handler,NULL)!=0)
{
perror("create err");
return -1;
}
printf("in mian\n");
while(1);//让进程不结束
return 0;
}
信号量同步
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <semaphore.h>
char buf[32] = {0};
sem_t sem;
void *myprint(void *arg)
{
//循环输出到终端
while(1)
{
sem_wait(&sem);//-1
if(!strcmp(buf,"quit"))
break;
printf("buf:%s\n",buf);
}
pthread_exit(0);
}
int main(int argc, char const *argv[])
{
pthread_t tid;
//1.初始化信号量
if(sem_init(&sem,0,0))
{
perror("init err");
return -1;
}
//创建线程
if(pthread_create(&tid,NULL,myprint,NULL)!=0)
{
perror("create err");
return -1;
}
//从终端获取
while(1)
{
fgets(buf,32,stdin);
//处理\n
if(buf[strlen(buf) -1] == '\n')
buf[strlen(buf) -1] = '\0';
sem_post(&sem);//+1
if(!strcmp(buf,"quit"))
break;
}
//回收线程
pthread_join(tid,NULL);
return 0;
}
互斥锁互斥
#include <stdio.h>
#include <semaphore.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
pthread_mutex_t lock;
pthread_cond_t cond;
int a[10] = {0,1,2,3,4,5,6,7,8,9};
void *inver(void *arg)
{
int temp;
while(1)
{
sleep(1);//让打印先抢到锁
pthread_mutex_lock(&lock);
//倒置
for(int i = 0;i < 5;i++)
{
temp = a[i];
a[i] = a[9 - i];
a[9 - i] = temp;
}
pthread_cond_signal(&cond);//产生条件变量
pthread_mutex_unlock(&lock);
}
}
void *myprint (void *arg)
{
while(1)
{
pthread_mutex_lock(&lock);//上锁
pthread_cond_wait(&cond,&lock);//如果没有条件产生时,解锁,当等待到条件产生时,上锁
//打印
for(int i = 0;i < 10; i++)
printf("%d ",a[i]);
putchar(10);
pthread_mutex_unlock(&lock);//解锁
}
}
int main(int argc, char const *argv[])
{
pthread_t tid1,tid2;
//初始化锁
pthread_mutex_init(&lock,NULL);
//初始化条件变量
pthread_cond_init(&cond,NULL);
//创建线程
if(pthread_create(&tid1,NULL,inver,NULL))
{
perror("tid1 err");
return -1;
}
if(pthread_create(&tid2,NULL,myprint,NULL))
{
perror("tid2 err");
return -1;
}
//阻塞回收进程
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
//销毁
pthread_mutex_destroy(&lock);
pthread_cond_destroy(&cond);
return 0;
}
信号
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/wait.h>
pid_t pid;
void saler(int sig)
{
if(sig == SIGINT)
kill(getppid(),SIGUSR1);
else if(sig == SIGQUIT)
kill(getppid(),SIGUSR2);
else if(sig == SIGUSR1)
{
printf("please get off the bus\n");
exit(0);
}
}
void driver(int sig)
{
if(sig == SIGUSR1)
printf("gogogo\n");
else if(sig == SIGUSR2)
printf("stop the bus\n");
else if(sig == SIGTSTP)
{
kill(pid,SIGUSR1);
wait(NULL);
exit(0);
}
}
int main(int argc, char const *argv[])
{
if((pid = fork()) < 0)
{
perror("fork err");
return -1;
}
else if(pid == 0)
{
//子进程管理员
signal(SIGTSTP,SIG_IGN);
signal(SIGINT,saler);
signal(SIGQUIT,saler);
signal(SIGUSR1,saler);
}
else
{
signal(SIGINT,SIG_IGN);
signal(SIGQUIT,SIG_IGN);
signal(SIGUSR1,driver);
signal(SIGUSR2,driver);
signal(SIGTSTP,driver);
}
while(1)
pause();
return 0;
}
守护进程
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char const *argv[])
{
//1.创建子进程,父进程退出
pid_t pid = fork();
if(pid < 0)
{
perror("fork err");
return -1;
}
else if(pid == 0)
{
//2. 在子进程里创建新会话,让子进程成为会话组长
setsid();
//3.改变运行目录为跟目录
chdir("/");
//4.重设文件权限掩码
umask(0);
//5.关闭文件描述符
for (int i = 0; i < 2; i++)
{
close(i);
}
//打开文件
int fd = open("./test.txt",O_RDWR | O_CREAT | O_TRUNC,0666);
if(fd < 0)
{
perror("open err");
return -1;
}
while(1)
{
write(fd,"hello\n",6);
sleep(1);
}
}
else
{
exit(0);
}
return 0;
}
共享内存
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
typedef struct
{
int flag;
char buf[32];
}SHM;
int main(int argc, char const *argv[])
{
key_t key = 1;
//创建或打开共享内存
int shmid;
shmid = shmget(key,128,IPC_CREAT | IPC_EXCL | 0666);
if(shmid < 0)
{
if(errno == 17)
//重新打开共享内存
shmid = shmget(key,128,0666);
else
{
perror("shmget err");
return -1;
}
}
printf("shmid:%d\n",shmid);
//映射共享内存
SHM *p = shmat(shmid,NULL,0);
if(p == (SHM *)-1)
{
perror("shmat err");
return -1;
}
fgets(p->buf,32,stdin);
printf("buf:%s\n",p->buf);
//取消映射
shmdt(p);
//删除共享内存
shmctl(shmid,IPC_RMID,NULL);
return 0;
}
消息队列
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h>
#include <string.h>
struct msgbuf
{
long mtype;
char name[32];
int age;
float score;
};
int main(int argc, char const *argv[])
{
//创建key
key_t key = ftok(".",'b');
if(key < 0)
{
perror("ftok err");
return -1;
}
printf("key:%d\n",key);
//创建或打开消息队列
int msgid = msgget(key,IPC_CREAT | IPC_EXCL | 0666);
if(msgid <= 0)
{
if(errno == 17)
msgid = msgget(key,0666);
else
{
perror("msgget err");
return -1;
}
}
printf("msgid:%d\n",msgid);
//按照类型添加/读取消息
struct msgbuf msg;
msg.mtype = 1;
strcpy(msg.name,"lihua");
msg.age = 18;
msg.score = 69.9;
msgsnd(msgid,&msg,sizeof(msg) - sizeof(long),0);
/
msg.mtype = 3;
strcpy(msg.name,"lihu");
msg.age = 8;
msg.score = 99.99;
msgsnd(msgid,&msg,sizeof(msg) - sizeof(long),0);
//读取消息
struct msgbuf buf;
msgrcv(msgid,&buf,sizeof(buf) - sizeof(long),2,0);
printf("name:%s\n",buf.name);
printf("age:%d\n",buf.age);
printf("score:%.2f\n",buf.score);
//再读一次
struct msgbuf buf;
msgrcv(msgid,&buf,sizeof(buf) - sizeof(long),1,0);
printf("name:%s\n",buf.name);
printf("age:%d\n",buf.age);
printf("score:%.2f\n",buf.score);
return 0;
}
TCP多进程服务器
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
//分别打印错误信息,函数名和行号到标准错误流中
#define ERR_MSG(msg) do{\
fprintf(stderr,"__%s__ __%s__ __%d__",__FILE__,__func__,__LINE__);\
perror(msg);\
}while(0)//循环只是为了去括号,无任何意义
#define IP "192.168.50.149" //ifconfig
int do_cil_msg(int newfd,struct sockaddr_in cin);
void headler(int sig);
int main(int argc, char const *argv[])
{
//创建流式套接字
int sfd = socket(AF_INET,SOCK_STREAM,0);
if(sfd < 0)
{
ERR_MSG("socket");
return -1;
}
printf("sock success sfd=%d\n",sfd);
//允许端口快速被覆盖重用。
int reuse = 1;
if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
{
ERR_MSG("setsockopt");
return -1;
}
printf("允许端口快速被覆盖重用成功\n");
//填充地址信息结构体,真实的地址信息结构体AF_INET:man 7 IP
struct sockaddr_in sin;//定义结构体变量,引出成员并填充地址
sin.sin_family = AF_INET; //这里填ipv4协议
sin.sin_port = htons(6666);//端口号的网络字节序1024~49151,将端口号转换成网络字节序
sin.sin_addr.s_addr = inet_addr(IP);//将ip地址的点分十进制转换成网络字节序,并存到sin下的sin_addr下的s_addr中
if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin)) < 0)
{
ERR_MSG("bind");
return -1;
}
printf("bind success __%d__\n",__LINE__);//输出当前行号
//将套接字设置为被动监听状态
if(listen(sfd,128) < 0)
{//将sfd套接字设置为被监听状态,允许同时有128个客户端未完成链接
ERR_MSG("listen");
return -1;
}
printf("listen success __%d__\n",__LINE__);//链接成功后输出行号
struct sockaddr_in cin;//存储客户端信息,定义存储地址信息结构体变量
socklen_t addrlen = sizeof(cin);//定义结构体类型存取结构体长度
//生成新的文件描述符与客户端通信
//int newfd = -1;
pid_t cpid = 0;//定义结构体变量,用来开启进程
while(1)
{
int newfd = accept(sfd,(struct sockaddr*)&cin,&addrlen);
if(newfd < 0)
{
ERR_MSG("accept");
return -1;
}
printf("[%s:%d] newfd=%d 客户端链接成功 __%d__\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,__LINE__);
cpid = fork();//客户端链接成功后开启进程
if(cpid == 0)
{
close(sfd);
do_cil_msg(newfd,cin);
close(newfd);
exit(0);
}
else if(cpid > 0)
{
close(newfd);
if(signal(17,headler) == SIG_ERR)
{
perror("signal");
return -1;
}
}
else
{
ERR_MSG("fork");
return -1;
}
}
//关闭
if(close(sfd) < 0)//关闭sfd套接字
{
ERR_MSG("close");
return -1;
}
return 0;
}
int do_cil_msg(int newfd,struct sockaddr_in cin)
{
char buf[128] = "";//定义字符型数组存取数据
ssize_t res = 0;//定义结构提变量接收返回值
while(1)
{
bzero(buf,sizeof(buf));//将buf数组清零
//接收
res = recv(newfd,buf,sizeof(buf),0);//从得到accept返回值的newfd套接字中
if(res <0)//返回值小于0,读取失败
{
ERR_MSG("recv");
return -1;
}
else if(0 == res)//返回值等于0,客户端下线
{
printf("[%s:%d] newfd=%d 客户端下线__%d__\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,__LINE__);
//输出转换后的ip地址和主机字节序,和新的文件描述符
break;
}
printf("[%s:%d] newfd=%d : %s __%d__\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,buf,__LINE__);
//输出ip地址和主机字节序,新的文件描述符和buf中的内容
//发送
strcat(buf,"*_*");//在buf数组的末尾追加*_*,证明服务器以收到数据
if(send(newfd,buf,sizeof(buf),0) < 0)//如果返回值小于0,发送失败
{
ERR_MSG("send");
return -1;
}
printf("send success __%d__\n",__LINE__);//发送成功后显示数据
}
return 0;
}
void headler(int sig)
{
//若成功回收到僵尸进程再收一次
//直到没有收到僵尸进程,解除循环
//==0,有子进程,没有僵尸进程
//==-1,没有子进程,也没有僵尸进程
while(waitpid(-1,NULL,WNOHANG) > 0);
return;
}
TCP多线程服务器
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <pthread.h>
//分别打印错误信息,函数名和行号到标准错误流中
#define ERR_MSG(msg) do{\
fprintf(stderr,"__%s__ __%s__ __%d__",__FILE__,__func__,__LINE__);\
perror(msg);\
}while(0)//循环只是为了去括号,无任何意义
//需要传入线程中的参数
struct msg
{
int newfd;
struct sockaddr_in cin;
};
void* deal_cil_msg(void* arg);
#define IP "192.168.50.149" //ifconfig
int main(int argc, char const *argv[])
{
//创建流式套接字
int sfd = socket(AF_INET,SOCK_STREAM,0);
if(sfd < 0)
{
ERR_MSG("socket");
return -1;
}
printf("sock success sfd=%d\n",sfd);
//允许端口快速被覆盖重用。
int reuse = 1;
if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
{
ERR_MSG("setsockopt");
return -1;
}
printf("允许端口快速被覆盖重用成功\n");
//填充地址信息结构体,真实的地址信息结构体AF_INET:man 7 IP
struct sockaddr_in sin;//定义结构体变量,引出成员并填充地址
sin.sin_family = AF_INET; //这里填ipv4协议
sin.sin_port = htons(6666);//端口号的网络字节序1024~49151,将端口号转换成网络字节序
sin.sin_addr.s_addr = inet_addr(IP);//将ip地址的点分十进制转换成网络字节序,并存到sin下的sin_addr下的s_addr中
if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin)) < 0)
{
ERR_MSG("bind");
return -1;
}
printf("bind success __%d__\n",__LINE__);//输出当前行号
//将套接字设置为被动监听状态
if(listen(sfd,128) < 0)
{//将sfd套接字设置为被监听状态,允许同时有128个客户端未完成链接
ERR_MSG("listen");
return -1;
}
printf("listen success __%d__\n",__LINE__);//链接成功后输出行号
struct sockaddr_in cin;//存储客户端信息,定义存储地址信息结构体变量
socklen_t addrlen = sizeof(cin);//定义结构体类型存取结构体长度
//生成新的文件描述符与客户端通信
//int newfd = -1;
pthread_t tid;//定义结构体变量,用来开启线程
struct msg info;
while(1)
{
int newfd = accept(sfd,(struct sockaddr*)&cin,&addrlen);
if(newfd < 0)
{
ERR_MSG("accept");
return -1;
}
printf("[%s:%d] newfd=%d 客户端链接成功 __%d__\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,__LINE__);
info.newfd = newfd;
info.cin = cin;
if(pthread_create(&tid,NULL,deal_cil_msg,&info) != 0)
{//出错会执行以下语句
fprintf(stderr,"pthread_create failed __%d__\n",__LINE__);
}
pthread_detach(tid);//分离线程,线程退出后由内核自动回收
}
//关闭
if(close(sfd) < 0)//关闭sfd套接字
{
ERR_MSG("close");
return -1;
}
return 0;
}
void* deal_cil_msg(void* arg)
{
int newfd = ((struct msg*)arg)->newfd;
struct sockaddr_in cin = ((struct msg*)arg)->cin;
char buf[128] = "";//定义字符型数组存取数据
ssize_t res = 0;//定义结构提变量接收返回值
while(1)
{
bzero(buf,sizeof(buf));//将buf数组清零
//接收
res = recv(newfd,buf,sizeof(buf),0);//从得到accept返回值的newfd套接字中
if(res <0)//返回值小于0,读取失败
{
ERR_MSG("recv");
break;
}
else if(0 == res)//返回值等于0,客户端下线
{
printf("[%s:%d] newfd=%d 客户端下线__%d__\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,__LINE__);
//输出转换后的ip地址和主机字节序,和新的文件描述符
break;
}
printf("[%s:%d] newfd=%d : %s __%d__\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,buf,__LINE__);
//输出ip地址和主机字节序,新的文件描述符和buf中的内容
//发送
strcat(buf,"*_*");//在buf数组的末尾追加*_*,证明服务器以收到数据
if(send(newfd,buf,sizeof(buf),0) < 0)//如果返回值小于0,发送失败
{
ERR_MSG("send");
break;
}
printf("send success __%d__\n",__LINE__);//发送成功后显示数据
}
//关闭
if(close(newfd) < 0)
{
ERR_MSG("close");
}
pthread_exit(NULL);
return 0;
}
selectTCP(多路复用)
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/select.h>
#define ERR_MSG(msg) do{\
fprintf(stderr,"__%s__ __%s__ __%d__",__FILE__,__func__,__LINE__);\
perror(msg);\
}while(0)
#define IP "192.168.50.149" //ifconfig
#define PORT 6666 //端口号 1024~49151
int main(int argc, char const *argv[])
{
//创建流式套接字
int sfd = socket(AF_INET,SOCK_STREAM,0);
//定义整形变量接收socket函数返回的文件描述副
if(sfd < 0)
{
ERR_MSG("socket");
return -1;
}
printf("create socket success cfd=%d __%d__\n",sfd,__LINE__);
int reuse = 1;
if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
{
ERR_MSG("setsockopt");
return -1;
}
printf("允许端口快速被覆盖重用成功\n");
struct sockaddr_in sin;
sin.sin_family = AF_INET; //这里填ipv4协议
sin.sin_port = htons(PORT);//端口号的网络字节序1024~49151,将端口号转换成网络字节序
sin.sin_addr.s_addr = inet_addr(IP);//将ip地址的点分十进制转换成网络字节序,并存到sin下的sin_addr下的s_addr中
if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin)) < 0)
{//将sin中得地址信息绑定到sfd套接字文件中(因为sin的变量类型不一样
//需要强制类型转换),最后可以使用sizeof直接算出sin结构体变量的大小
ERR_MSG("bind");
return -1;
}
printf("bind success __%d__\n",__LINE__);//输出当前行号
//将套接字设置为被动监听状态
if(listen(sfd,128) < 0)
{//将sfd套接字设置为被监听状态,允许同时有128个客户端未完成链接
ERR_MSG("listen");
return -1;
}
printf("listen success __%d__\n",__LINE__);//链接成功后输出行号
//创建一个集合
fd_set readfds,tempfds;
//清空结构体,完成初始化
FD_ZERO(&readfds);
FD_ZERO(&tempfds);
FD_SET(0,&readfds);//将0添加到集合中
FD_SET(sfd,&readfds);//将sfd添加到集合中
int maxfd = sfd;
int s_res = 0;
struct sockaddr_in cin;//存储客户地址信息
socklen_t addrlen = sizeof(cin);
struct sockaddr_in savecin[1024-3];
int newfd = -1;
char buf[128] = "";
ssize_t res = 0;
while(1)
{
tempfds = readfds;
//调用select函数,让内核检测集合中的文件描述符
s_res = select(maxfd+1,&tempfds,NULL,NULL,NULL);
if(s_res <0)
{
ERR_MSG("select");
return -1;
}
else if(0 == s_res)
{
printf("time out...\n");
break;
}
printf("__%d__",__LINE__);
for(int i=0;i<=maxfd;i++)
{
if(!FD_ISSET(i,&tempfds))
//能运行到当前位置,则说明i代表的文件描述符在集合中
continue;
if(0 == i)
{
printf("触发输入事件\n");
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1] = 0;
printf("%s\n",buf);
}
else if(sfd == i)
{
printf("触发客户端链接事件\n");
newfd = accept(sfd,(struct sockaddr*)&cin,&addrlen);
if(newfd < 0)
{
ERR_MSG("accept");
return -1;
}
printf("[%s:%d] newfd=%d 客户端链接成功 __%d__\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,__LINE__);
savecin[newfd-3] = cin;//将cin通过newfd另存到数组中
//将newfd添加到读集合中
FD_SET(newfd,&readfds);
maxfd = maxfd>newfd?maxfd:newfd;
}
else
{
bzero(buf,sizeof(buf));
printf("触发客户端交互事件\n");
res = recv(i,buf,sizeof(buf),0);
if(res <0)//返回值小于0,读取失败
{
ERR_MSG("recv");
return -1;
}
else if(0 == res)//返回值等于0,客户端下线
{
printf("[%s:%d] newfd=%d 客户端下线__%d__\n",\
inet_ntoa(savecin[i-3].sin_addr),ntohs(savecin[i-3].sin_port),newfd,__LINE__);
//输出转换后的ip地址和主机字节序,和新的文件描述符
//关闭文件描述符
close(i);
//将文件描述符从集合中移除
FD_CLR(i,&readfds);
//更新maxfd从最大maxfd往小便利,
//若该文件描述符在集合中,则该文件描述符就是最大的
int j = maxfd;
while(!FD_ISSET(j,&readfds) && j-->=0);
maxfd = j;
continue;
}
printf("[%s:%d] newfd=%d : %s __%d__\n",\
inet_ntoa(savecin[i-3].sin_addr),ntohs(savecin[i-3].sin_port),newfd,buf,__LINE__);
strcat(buf,"*_*");//在buf数组的末尾追加*_*,证明服务器以收到数据
if(send(i,buf,sizeof(buf),0) < 0)//如果返回值小于0,发送失败
{
ERR_MSG("send");
return -1;
}
printf("send success __%d__\n",__LINE__);//发送成功后显示数据
}
}
}
//关闭
if(close(sfd) < 0)//关闭cfd套接字文件描述符
{
ERR_MSG("close");
return -1;
}
return 0;
}
TCP_unix(进程之间通信服务器)
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/un.h>
//分别打印错误信息,函数名和行号到标准错误流中
#define ERR_MSG(msg) do{\
fprintf(stderr,"__%s__ __%s__ __%d__",__FILE__,__func__,__LINE__);\
perror(msg);\
}while(0)//循环只是为了去括号,无任何意义
int main(int argc, char const *argv[])
{
//创建流式套接字
int sfd = socket(AF_UNIX,SOCK_STREAM,0);
if(sfd < 0)
{
ERR_MSG("socket");
return -1;
}
printf("sock success sfd=%d\n",sfd);
//判断文件是否存在
if(access("./unix",F_OK) == 0)
{
//若存在删除
if(unlink("./unix") < 0)
{
ERR_MSG("unlink");
return -1;
}
}
//填充地址信息结构体,真实的地址信息结构体AF_INET:man 7 IP
struct sockaddr_un sun;//定义结构体变量,引出成员并填充地址
sun.sun_family = AF_UNIX;
strcpy(sun.sun_path,"./unix");
if(bind(sfd,(struct sockaddr*)&sun,sizeof(sun)) < 0)
{//将sin中得地址信息绑定到sfd套接字文件中(因为sin的变量类型不一样
//需要强制类型转换),最后可以使用sizeof直接算出sin结构体变量的大小
ERR_MSG("bind");
return -1;
}
printf("bind success __%d__\n",__LINE__);//输出当前行号
if(listen(sfd,128) < 0)
{//将sfd套接字设置为被监听状态,允许同时有128个客户端未完成链接
ERR_MSG("listen");
return -1;
}
printf("listen success __%d__\n",__LINE__);//链接成功后输出行号
struct sockaddr_in cun;//存储客户端信息,定义存储地址信息结构体变量
socklen_t addrlen = sizeof(cun);//定义结构体类型存取结构体长度
//生成新的文件描述符与客户端通信
int newfd = accept(sfd,(struct sockaddr*)&cun,&addrlen);
if(newfd < 0)
{
ERR_MSG("accept");
return -1;
}
printf("[] newfd=%d 客户端链接成功 __%d__\n",newfd,__LINE__);
//客户端链接成功后输出,转换后的ip地址和转换后的主机字节序,和行号
char buf[128] = "";//定义字符型数组存取数据
ssize_t res = 0;//定义结构提变量接收返回值
while(1)
{
bzero(buf,sizeof(buf));//将buf数组清零
//接收
res = recv(newfd,buf,sizeof(buf),0);//从得到accept返回值的newfd套接字中
//接收缓冲区的数据,并存储在数组中,用sizeof算出指定读取字节最后用0表示以阻塞方式
//读取
if(res <0)//返回值小于0,读取失败
{
ERR_MSG("recv");
return -1;
}
else if(0 == res)//返回值等于0,客户端下线
{
printf("[] newfd=%d 客户端下线__%d__\n",newfd,__LINE__);
//输出转换后的ip地址和主机字节序,和新的文件描述符
break;
}
printf("[] newfd=%d : %s __%d__\n",newfd,buf,__LINE__);
//输出ip地址和主机字节序,新的文件描述符和buf中的内容
//发送
strcat(buf,"*_*");//在buf数组的末尾追加*_*,证明服务器以收到数据
if(send(newfd,buf,sizeof(buf),0) < 0)//如果返回值小于0,发送失败
{//send函数可以将but数组中的数据发送给accept函数中得到的文件描述符,
//第三项是大小,第四项0是阻塞发送
ERR_MSG("send");
return -1;
}
printf("send success __%d__\n",__LINE__);//发送成功后显示数据
}
//关闭
if(close(newfd) < 0)//关闭newfd套接字
{
ERR_MSG("close");//关闭失败返回-1,并输出错误内容
return -1;
}
if(close(sfd) < 0)//关闭sfd套接字
{
ERR_MSG("close");
return -1;
}
return 0;
}
TCP进程之间通信客户端
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/un.h>
#define ERR_MSG(msg) do{\
fprintf(stderr,"__%s__ __%s__ __%d__",__FILE__,__func__,__LINE__);\
perror(msg);\
}while(0)
int main(int argc, char const *argv[])
{
//创建流式套接字
int cfd = socket(AF_UNIX,SOCK_STREAM,0);
//定义整形变量接收socket函数返回的文件描述副
if(cfd < 0)
{
ERR_MSG("socket");
return -1;
}
printf("create socket success cfd=%d __%d__\n",cfd,__LINE__);
//绑定客户端自身的地址信息结构体---》非必须绑定
//若客户端没有绑定地址信息,
//测操作系统会自动帮客户端绑定本机IP,以及49151~65535内的随机端口
//填充服务器的地址信息结构体,给connect函数使用
//要链接哪个服务器,就填哪个服务器的地址信息
struct sockaddr_un sun;
sun.sun_family = AF_UNIX;
strcpy(sun.sun_path,"./unix");
//链接服务器
if(connect(cfd,(struct sockaddr*)&sun,sizeof(sun)) < 0)//当返回值小于0,失败
{//通过connect函数链接服务器:将指定要链接的文件描述符绑定sun的结构体变量链接服务器,
ERR_MSG("connect");
return -1;
}
printf("connect success __%d__\n",__LINE__);
//成功后返回行号
char buf[128] = "";//定义字符型数组
ssize_t res = 0;//定义结构体变量,接收返回值
while(1)
{
//从终端获取数据
printf("请输入>>> ");
fgets(buf,sizeof(buf),stdin);//从标准输入流中读取数据,存入到buf数组中
buf[strlen(buf)-1] = 0;//将buf的最后一位‘\n’改为0
//发送
if(send(cfd,buf,sizeof(buf),0) < 0)//返回值小于0,发送失败
{//通过cfd套接字文件描述符向缓冲区发送buf中的数据
ERR_MSG("send");
return -1;
}
printf("send success __%d__\n",__LINE__);//成功输出行号
//接收
bzero(buf,sizeof(buf));//将buf数组清零
res = recv(cfd,buf,sizeof(buf),0);
//通过该函数从该套接字文件描述符中接收数据,并存入buf数组中
if(res < 0)//如果返回值小于0
{
ERR_MSG("recv");//接收失败
return -1;
}
else if(0 == res)//返回之等于0,断线
{
printf("服务器离线\n");
break;
}
printf("%s __%d__\n",buf,__LINE__);//接收成功输出buf数组中的内容和行号
}
//关闭
if(close(cfd) < 0)//关闭cfd套接字文件描述符
{
ERR_MSG("close");
return -1;
}
return 0;
}
UDP组播服务器
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#define ERR_MSG(msg) do{\
fprintf(stderr, "__%s__ __%s__ __%d__ ", __FILE__, __func__, __LINE__);\
perror(msg);\
}while(0)
#define PORT 6666 //1024~49151
#define GRP_IP "224.1.2.3" //组播IP
#define LOL_IP "192.168.50.149" //本机IP
int main(int argc, const char *argv[])
{
//创建报式套接字
int sfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sfd < 0)
{
ERR_MSG("socket");
return -1;
}
printf("sfd = %d __%d__\n", sfd, __LINE__);
//加入多播组
struct ip_mreqn mq;
mq.imr_multiaddr.s_addr = inet_addr(GRP_IP);
mq.imr_address.s_addr = inet_addr(LOL_IP);
mq.imr_ifindex = 2; //0 网卡设备的索引号
if(setsockopt(sfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mq,sizeof(mq)) < 0)
{
ERR_MSG("setsockopt");
return -1;
}
printf("加入多播组 %s : %d 成功\n",GRP_IP,PORT);
//填充服务器的地址信息结构体, AF_INET: man 7 ip
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT); //1024~49151
sin.sin_addr.s_addr = inet_addr(GRP_IP); //ifconfig
//绑定服务器自身的地址信息
if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
{
ERR_MSG("bind");
return -1;
}
printf("bind success __%d__\n", __LINE__);
char buf[128] = "";
struct sockaddr_in cin; //存储客户端的地址信息
socklen_t addrlen = sizeof(cin);
ssize_t res = 0;
while(1)
{
bzero(buf, sizeof(buf));
//接收
res = recvfrom(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&cin, &addrlen);
if(res < 0)
{
ERR_MSG("recvfrom");
return -1;
}
printf("[%s:%d] : %s __%d__\n", \
inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), buf, __LINE__);
}
//关闭
if(close(sfd) < 0)
{
ERR_MSG("close");
return -1;
}
return 0;
}
UDP组播客户端
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#define ERR_MSG(msg) do{\
fprintf(stderr, "__%s__ __%s__ __%d__ ", __FILE__, __func__, __LINE__);\
perror(msg);\
}while(0)
#define PORT 6666 //1024~49151
#define IP "224.1.2.3" //组播IP224.0.0.0-239.255.255.255
int main(int argc, const char *argv[])
{
//创建报式套接字
int cfd = socket(AF_INET, SOCK_DGRAM, 0);
if(cfd < 0)
{
ERR_MSG("socket");
return -1;
}
printf("cfd = %d __%d__\n", cfd, __LINE__);
//绑定客户端自身的地址信息---》非必须绑定
//若不绑定则操作系统会自动给客户端绑定上一个可用IP以及随机端口。
//填充服务器的地址信息结构体,给sendto函数使用
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT); //服务器的端口
sin.sin_addr.s_addr = inet_addr(IP); //服务器的IP
char buf[128] = "";
ssize_t res = 0;
while(1)
{
bzero(buf, sizeof(buf));
printf("请输入>>> ");
fgets(buf, sizeof(buf), stdin);
buf[strlen(buf)-1] = 0;
if(sendto(cfd, buf, sizeof(buf), 0, (struct sockaddr*)&sin, sizeof(sin)) < 0)
{
ERR_MSG("sendto");
return -1;
}
printf("sendto success __%d__\n", __LINE__);
}
//关闭
if(close(cfd) < 0)
{
ERR_MSG("close");
return -1;
}
return 0;
}
UDP广播
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <string.h>
#define ERR_MSG(msg) do{\
fprintf(stderr,"__%s__ __%s__ __%d__",__FILE__,__func__,__LINE__);\
perror(msg);\
}while(0)
#define IP "192.168.50.255" //ifconfig
#define PORT 6666 //端口号 1024~49151
int main(int argc, char const *argv[])
{
//创建套接字
int cfd = socket(AF_INET,SOCK_DGRAM,0);
if(cfd < 0)
{
ERR_MSG("socket");
return -1;
}
printf("std = %d __%d__\n",cfd,__LINE__);
//设置允许广播
int broad = 1;
if(setsockopt(cfd, SOL_SOCKET, SO_BROADCAST, &broad, sizeof(broad)) < 0)
{
ERR_MSG("setsockopt");
return -1;
}
printf("设置广播成功\n");
//绑定ip地址
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(IP);
//接收对方数据
char buf[128]="";
struct sockaddr_in dstAddr;
socklen_t addrlen = sizeof(dstAddr);
ssize_t res = 0;
while(1)
{
bzero(buf,sizeof(buf));
printf("请输入>>> ");
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1] = 0;
//发送
if(sendto(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,sizeof(sin)) < 0)
{
ERR_MSG("sendto");
return -1;
}
printf("sendto success __%d__\n",__LINE__);
}
if(close(cfd) < 0)
{
ERR_MSG("close");
return -1;
}
return 0;
}