实验七 网络编程

一、实验目的与任务

目的:了解掌握操作系统消息队列、信号量的特点与功能,学会借助消息队列、信号量的功能函数进行编程。

任务:利用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;
}

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值