一、实验目的与任务
目的:了解掌握操作系统消息队列、信号量的特点与功能,学会借助消息队列、信号量的功能函数进行编程。
任务:利用C语言指令编写程序调用消息队列、信号量函数,完成相应功能。
二、实验设备
装有Linux操作系统的计算机一台。
三、实验目的
1、实验目的:
利用地址处理函数访问网络地址以及编程实现域名与IP信息解析,练习套接字基本应用。
2、实验安排方式:采用1人1组,上机在Linux系统下进行编程实验。
四、实验内容
利用线程和socket套接字相关知识设计一个C/S架构的聊天系统,服务器和客户端可以互发信息,实现实时通信。
服务器:
客户端:
serve.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>
#define M 30
void *pthrFunc1(void *arg)
{
char buf[M];
int connFd = *((int *)arg);
while(1)
{
memset(buf,0,sizeof(buf));
//printf("send:");
scanf("%s",buf);
if(0 == strcmp(buf,"quit"))
{
break;
}
int ret = send(connFd,buf,sizeof(buf),0);
if(ret < 0)
{
perror("send error");
close(connFd);
return NULL;
}
}
return NULL;
}
void *pthrFunc2(void *arg)
{
char buf[M];
int ret;
int connFd = *((int *)arg);
while(1)
{
int ret = recv(connFd,buf,sizeof(buf),0);
if(ret < 0)
{
perror("recv error");
close(connFd);
return NULL;
}
if(0 == ret)
{
break;
}
printf("recv:%s\n",buf);
}
return NULL;
}
int main()
{
//创建并打开套接字
int sockFd = socket(PF_INET,SOCK_STREAM,0);
if(sockFd < 0)
{
perror("socket error");
return -1;
}
//绑定服务器地址信息
struct sockaddr_in servAddr = {0};
servAddr.sin_family = PF_INET;
servAddr.sin_port = htons(8888);
servAddr.sin_addr.s_addr = inet_addr("0.0.0.0");
int ret = bind(sockFd,(struct sockaddr *)&servAddr,sizeof(servAddr));
if(ret < 0)
{
perror("bind error");
return -1;
}
printf("bind OK\n");
//创建监听队列
ret = listen(sockFd,10);
if(ret < 0)
{
perror("listen error");
close(sockFd);
return -1;
}
printf("listen OK");
//等待并建立连接
struct sockaddr_in cliAddr = {0};
socklen_t len = sizeof(cliAddr);
int connFd = accept(sockFd,(struct sockaddr *)&cliAddr,&len);
if(connFd < 0)
{
perror("accept error");
close(sockFd);
return -1;
}
printf("IP:%s,PORT:%d,accept OK\n",inet_ntoa(cliAddr.sin_addr),ntohs(cliAddr.sin_port));
//创建两个子线程,一个循环写一个循环读
pthread_t pth1,pth2;
pthread_create(&pth1,NULL,pthrFunc1,&connFd);
pthread_create(&pth1,NULL,pthrFunc2,&connFd);
//主线程等待回收子线程
pthread_join(pth1,NULL);
pthread_join(pth2,NULL);
//关闭套接字
close(sockFd);
close(connFd);
return 0;
}
client.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>
#define M 30
void *pthrFunc1(void *arg)
{
char buf[M];
int sockFd = *((int *)arg);
while(1)
{
memset(buf,0,sizeof(buf));
//printf("send:");
scanf("%s",buf);
if(0 == strcmp(buf,"quit"))
{
break;
}
int ret = send(sockFd,buf,sizeof(buf),0);
if(ret < 0)
{
perror("send error");
close(sockFd);
return NULL;
}
}
return NULL;
}
void *pthrFunc2(void *arg)
{
char buf[M];
int ret;
int sockFd = *((int *)arg);
while(1)
{
int ret = recv(sockFd,buf,sizeof(buf),0);
if(ret < 0)
{
perror("recv error");
close(sockFd);
return NULL;
}
if(0 == ret)
{
break;
}
printf("recv:%s\n",buf);
}
return NULL;
}
int main()
{
char servIP[M];
printf("servIP:");
scanf("%s",servIP);
//创建并打开套接字
int sockFd = socket(PF_INET,SOCK_STREAM,0);
if(sockFd < 0)
{
perror("socket error");
return -1;
}
printf("socket OK\n");
//连接服务器
struct sockaddr_in servAddr = {0};
servAddr.sin_family = PF_INET;
servAddr.sin_port = htons(8888);
servAddr.sin_addr.s_addr = inet_addr(servIP);//服务器ip
int ret = connect(sockFd,(struct sockaddr *)&servAddr,sizeof(servAddr));
if(ret < 0)
{
perror("connect error");
close(sockFd);
return -1;
}
printf("connect OK\n");
//创建两个子线程,一个循环写一个循环读
pthread_t pth1,pth2;
pthread_create(&pth1,NULL,pthrFunc1,&sockFd);
pthread_create(&pth2,NULL,pthrFunc2,&sockFd);
//主线程等待回收子线程
pthread_join(pth1,NULL);
pthread_join(pth2,NULL);
//关闭套接字
close(sockFd);
return 0;
}