线程实现邮箱通信-实验报告
邮件传送协议实验报告

实验名称:邮件传送协议实验实验日期:2023年X月X日实验地点:实验室实验人员:[你的姓名]一、实验目的1. 了解邮件传送协议(SMTP)的基本原理和流程。
2. 掌握使用SMTP协议发送邮件的方法。
3. 熟悉邮件客户端的配置和使用。
二、实验原理邮件传送协议(SMTP,Simple Mail Transfer Protocol)是一种用于在互联网上传输电子邮件的协议。
SMTP协议定义了邮件客户端(如Outlook、Foxmail等)与邮件服务器之间交换邮件的规则和格式。
本实验旨在通过模拟SMTP协议的工作过程,加深对邮件传送原理的理解。
三、实验内容1. 配置邮件客户端2. 编写SMTP发送邮件的代码3. 分析SMTP协议的响应和错误信息4. 测试邮件发送功能四、实验步骤1. 配置邮件客户端(1)打开邮件客户端,如Outlook。
(2)在“文件”菜单中选择“账户设置”。
(3)点击“添加账户”,选择“电子邮件账户”。
(4)填写用户名、密码、邮箱服务器地址等信息。
(5)完成账户配置,测试邮件发送功能。
2. 编写SMTP发送邮件的代码(1)选择编程语言,如Python。
(2)导入必要的库,如smtplib和email。
(3)创建一个SMTP对象,连接到邮件服务器。
(4)创建一个邮件对象,填写发件人、收件人、主题和正文等信息。
(5)发送邮件,并捕获SMTP协议的响应和错误信息。
3. 分析SMTP协议的响应和错误信息(1)根据SMTP协议的响应代码,判断邮件发送是否成功。
(2)分析SMTP协议的错误信息,找出可能的问题原因。
(3)根据错误信息,对邮件发送代码进行修改和优化。
4. 测试邮件发送功能(1)使用配置好的邮件客户端,发送一封邮件。
(2)使用编写的SMTP发送邮件代码,发送一封邮件。
(3)比较两种方式发送邮件的结果,验证邮件发送功能。
五、实验结果与分析1. 邮件客户端配置成功,邮件发送功能正常。
2. 使用Python编写的SMTP发送邮件代码,邮件发送成功。
线程实例实验报告总结

一、实验目的本次实验旨在通过实例操作,深入了解线程的概念、创建、同步与通信机制,以及线程在实际编程中的应用。
通过实验,提高对线程的理解和运用能力,为以后开发多线程程序打下坚实基础。
二、实验环境1. 操作系统:Windows 102. 开发工具:Visual Studio 20193. 编程语言:C#三、实验内容1. 线程的基本概念线程是程序执行的最小单位,是操作系统进行资源分配和调度的基本单位。
线程具有以下特点:(1)线程是轻量级的,创建、销毁线程的开销较小。
(2)线程共享进程的资源,如内存、文件等。
(3)线程之间可以并发执行。
2. 线程的创建在C#中,可以使用以下方式创建线程:(1)使用Thread类```csharpThread thread = new Thread(new ThreadStart(MethodName));thread.Start();```(2)使用lambda表达式```csharpThread thread = new Thread(() => MethodName());thread.Start();```(3)使用匿名方法```csharpThread thread = new Thread(delegate () { MethodName(); });thread.Start();```3. 线程的同步线程同步是指多个线程在执行过程中,为了防止资源冲突而采取的协调机制。
C#提供了以下同步机制:(1)互斥锁(Mutex)```csharpMutex mutex = new Mutex();mutex.WaitOne();// 线程同步代码mutex.ReleaseMutex();```(2)信号量(Semaphore)```csharpSemaphore semaphore = new Semaphore(1, 1);semaphore.WaitOne();// 线程同步代码semaphore.Release();```(3)读写锁(ReaderWriterLock)```csharpReaderWriterLock rwlock = new ReaderWriterLock();rwlock.AcquireReaderLock();// 读取操作rwlock.ReleaseReaderLock();```4. 线程的通信线程通信是指线程之间传递消息、共享数据的过程。
邮件接收程序的设计与实现-专业实习报告

邮件接收程序的设计与实现
邮件接收程序比邮件发送程序要复杂 一些,这个程序首先需要使用MAPI消息控 件的Fetch方法读取邮件,这个过程将把用 户收件箱中所有未读邮件全部装入MAPI消 息控件中。接着,检查MAPI消息控件的 MsgCount属性以确定通过Fetch方法读取 的邮件的总数,
邮件接收程序的设计与实现
邮件接收程序的设计与实现
2:cmdNext的Click事件代码: Private Sub cmdNext_Click() If MAPIMessages1.MsgIndex < MAPIMessages1.MsgCount - 1 Then MAPIMessages1.MsgIndex = MAPIMessages1.MsgIndex + 1 /当收取信件超过1封 的时候,通过“下一封”按钮查看后面的信件 DisplayMessage Else Beep End If End Sub
邮件接收程序的设计与实现
邮件接收程序的设计与实现
代码实现过程
1:cmdPrevious的Click事件代码: Private Sub cmdPrevious() If MAPIMessages1.MsgIndex > 0 Then MAPIMessages1.MsgIndex = MAPIMessages1.MsgIndex - 1 /当收取信件超过1封 的时候,通过“上一封”按钮查看前面的信件 DisplayMessage Else Beep End If End Sub
。
3、在Form1中加入三个Label控件和一个 TextBox控件,将三个标签控件的名称属性 分别设置为“lblMsgDateReceived”、 “lblMsgOrigDisplayName”和 “IblMsgSubject”,将TextBox控件的名称 属性设置为“txtMsgNoteText”,并将标签 控件的(name)属性和文本框控件的Text 属性的内容清空。这四个控件将分别用于 显示邮件的日期、发件人、主题和内容
电子邮件客户端程序设计与实现实验报告

电子邮件客户端程序设计与实现实验报告
本次实验中,我编写一个电子邮件客户端程序,可用于发送和接收电子邮件。
该客户端程序可以支持 Simple Mail Transfer Protocol(SMTP)协议和Post Office Protocol (POP)协议,并可以连接到互联网上的邮件服务器。
首先,我采用经典的TCP/IP Socket通信库和该语言支持的SMTP/POP客户端函数,其中用于通过SMTP/POP客户端发送和接收邮件信息的核心功能函数有:协议调用,信息发送接收,文本处理和回复处理,以及异常处理等。
接着,我采用系统调用和网络函数的方式与服务器建立起连接,查找用户邮箱,读取邮件信息,发送邮件等。
最后,我利用用户界面和相应的事件处理机制,使用户能够较便捷的发送和接收邮件。
实验结果显示,编写的客户端程序可以较为便捷地连接到互联网上的邮件服务器,无论是发送邮件还是接收邮件都能较轻松地实现;并支持相应的错误处理和超时机制,使得整个电子邮件通信机制更加健全安全。
总之,本实验中,我编写了一个邮件客户端程序,可以支持SMTP/POP协议,可以连接互联网上的邮件服务器,实现电子邮件的发送和接收,该程序的执行结果也得到了较为理想的效果。
邮件服务器实训报告

邮件服务器的配置实验准备工作:1、在VM中打开2003和XP虚拟机各两台,并进行如下设置:2、在2003中安装应用程序服务器(选择SMTP服务)、电子邮件服务和DNS服务。
<SMTP组件选择时抓图><电子邮件服务选择时抓图>邮件服务器配置实训内容:总体要求:在2003上建立域的邮件服务器,新建邮箱mail01、mail02,关联Windows 账户,密码均为111。
在XP上OE添加mail01@S学号.net邮箱;在win 2003 上配置OE添加mail02@S学号.net。
这两个帐号能通过2003上的SMTP相互发送邮件,通过2003上的POP3服务接受邮件。
具体步骤:第一步、在DNS服务中添加域“S学号.net”,如“”,并添加主机记录mail指向2003服务器、再添加邮件交换记录指向。
<DNS记录抓图>第二步、在XP上使用nslookup测试域的邮件记录。
提示:set type=mx;<测试正常的抓图>第三步、在POP3服务管理工具中,新建域“”,要求设置身份验证方法为:集成Windows身份验证”。
设置磁盘配额:新用户限额100MB。
并在其中添加两个邮箱“mail01”、“mail02”并关联Windows用户,密码为111。
<域设置时的抓图><磁盘配额限制的抓图><完成后的抓图>第四步、在IIS管理器总,设置SMTP服务器常规属性-IP地址。
<完成后的抓图>********以下使用XP上的OE进行邮件服务器的测试********第五步、在XP上打开OE,添加邮件账户mail01,SMTP、POP3服务器均为2003服务器。
<邮件账户属性的服务器选项卡抓图>第六步、在windows2003上打开OE,添加邮件账户mail02,SMTP、POP3服务器均为2003服务器。
<邮件账户属性的常规选项卡抓图>第七步、在OE中分别发送以下二封邮件:●Mail01 to mail02●Mail02 to mail01查看收件箱接收情况。
计算网络邮件实验报告

一、实验目的1. 理解电子邮件的工作原理;2. 掌握电子邮件系统的基本架构;3. 学习使用电子邮件客户端发送和接收邮件;4. 了解电子邮件安全性和隐私保护措施。
二、实验环境1. 操作系统:Windows 102. 浏览器:Chrome3. 邮件客户端:Outlook4. 邮件服务器:Gmail三、实验内容1. 邮件系统的基本架构2. 电子邮件客户端的使用3. 邮件发送与接收4. 邮件安全性与隐私保护四、实验步骤1. 邮件系统的基本架构(1)了解电子邮件的工作原理:电子邮件系统采用SMTP(Simple Mail Transfer Protocol,简单邮件传输协议)进行邮件的发送和接收。
用户通过邮件客户端(如Outlook、Foxmail等)向邮件服务器发送邮件,邮件服务器将邮件存储在收件人的邮箱中,收件人通过邮件客户端接收邮件。
(2)学习电子邮件系统的基本架构:电子邮件系统主要由以下几个部分组成:1. 用户:使用邮件客户端发送和接收邮件;2. 邮件客户端:负责发送和接收邮件;3. 邮件服务器:负责存储和管理邮件;4. SMTP服务器:负责邮件的发送和传输;5. POP3/IMAP服务器:负责邮件的接收。
2. 电子邮件客户端的使用(1)安装邮件客户端:以Outlook为例,下载并安装Outlook软件。
(2)配置邮件客户端:打开Outlook,进入“文件”菜单,选择“添加账户”,然后按照提示填写邮件服务提供商(如Gmail)、用户名、密码等信息。
3. 邮件发送与接收(1)撰写邮件:在Outlook中,点击“新建邮件”按钮,填写收件人地址、主题和正文,然后点击“发送”。
(2)接收邮件:Outlook会自动检查邮箱,并将新收到的邮件显示在收件箱中。
4. 邮件安全性与隐私保护(1)使用SSL加密:在配置邮件客户端时,选择使用SSL加密连接,以保护邮件传输过程中的安全性。
(2)设置垃圾邮件过滤:在Outlook中,可以设置垃圾邮件过滤规则,避免接收垃圾邮件。
Java实现多线程邮件发送

Java实现多线程邮件发送 利⽤java多线程技术配合线程池实现多任务邮件发送.1.基本邮件发送MailSenderpackage hk.buttonwood.ops.email;import java.io.File;import java.util.Date;import java.util.Enumeration;import java.util.Properties;import java.util.Vector;import javax.activation.DataHandler;import javax.activation.FileDataSource;import javax.mail.Address;import javax.mail.AuthenticationFailedException;import javax.mail.BodyPart;import javax.mail.Message;import javax.mail.MessagingException;import javax.mail.Multipart;import javax.mail.Session;import javax.mail.Transport;import javax.mail.internet.InternetAddress;import javax.mail.internet.MimeBodyPart;import javax.mail.internet.MimeMessage;import javax.mail.internet.MimeMultipart;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/*** 简单邮件(带附件的邮件)发送器*/public class MailSender {private Logger logger = LoggerFactory.getLogger(MailSender.class);public static void main(String[] args) {// 这个类主要是设置邮件MailSenderInfo mailInfo = new MailSenderInfo();mailInfo.setMailServerHost("");mailInfo.setMailServerPort("25");mailInfo.setValidate(true);mailInfo.setUserName("151********");mailInfo.setPassword("myb1991517");// 您的邮箱密码mailInfo.setFromAddress("151********@");mailInfo.setToAddress("930147677@");mailInfo.setSubject("windowfg");mailInfo.setContent("asgjhkhl");// 这个类主要来发送邮件MailSender sms = new MailSender();Vector<File> files = new Vector<File>();files.addElement(new File("/home/maybo/myProject/2015-11-04/mt_2015-11-04_2.pdf"));mailInfo.setFile(files);sms.sendWithAttachment(mailInfo);// 发送⽂体格式// sms.sendHtmlMail(mailInfo);//发送html格式}/*** 发送邮件*/public MailState sendWithAttachment(MailSenderInfo info) {MailState mailState=new MailState();mailState.setDate(info.getDate());mailState.setState(MailState.SUCCESS);mailState.setDesc("邮箱发送成功!");mailState.setAddress(info.getToAddress());Session session = null;Properties props = System.getProperties();props.put("mail.smtp.host", info.getMailServerHost());if (info.isValidate()) { // 服务器需要⾝份认证props.put("mail.smtp.auth", "true");MyAuthenticator smtpAuth = new MyAuthenticator(info.getUserName(), info.getPassword());session = Session.getDefaultInstance(props, smtpAuth);} else {props.put("mail.smtp.auth", "false");session = Session.getDefaultInstance(props, null);}//session.setDebug(true);Transport trans = null;try {Address from_address = new InternetAddress(info.getFromAddress(), info.getUserName()); msg.setFrom(from_address);} catch (java.io.UnsupportedEncodingException e) {//e.printStackTrace();mailState.setState(MailState.ERROR);String message = "邮件发送失败!";mailState.setDesc(message);}InternetAddress[] address = { new InternetAddress(info.getToAddress()) };msg.setRecipients(Message.RecipientType.TO, address);msg.setSubject(info.getSubject());Multipart mp = new MimeMultipart();MimeBodyPart mbp = new MimeBodyPart();mbp.setContent(info.getContent().toString(), "text/html;charset=gb2312");mp.addBodyPart(mbp);if (!info.getFile().isEmpty()) {// 有附件Enumeration<?> efile = info.getFile().elements();while (efile.hasMoreElements()) {mbp = new MimeBodyPart();String filename = efile.nextElement().toString(); // 选择出每⼀个附件名FileDataSource fds = new FileDataSource(filename); // 得到数据源mbp.setDataHandler(new DataHandler(fds)); // 得到附件本⾝并⾄⼊BodyPartmbp.setFileName(fds.getName()); // 得到⽂件名同样⾄⼊BodyPartmp.addBodyPart(mbp);}info.getFile().removeAllElements();}msg.setContent(mp); // Multipart加⼊到信件msg.setSentDate(new Date()); // 设置信件头的发送⽇期// 发送信件msg.saveChanges();trans = session.getTransport("smtp");trans.connect(info.getMailServerHost(), info.getUserName(), info.getPassword());trans.sendMessage(msg, msg.getAllRecipients());trans.close();} catch (AuthenticationFailedException e) {mailState.setState(MailState.ERROR);String message = "邮件发送失败!错误原因:\n" + "⾝份验证错误!";mailState.setDesc(message);// e.printStackTrace();} catch (MessagingException e) {//e.printStackTrace();String message = "邮件发送失败!错误原因:" + e.getMessage();mailState.setDesc(message);mailState.setState(MailState.ERROR);}return mailState;}/*** 以⽂本格式发送邮件** @param mailInfo* 待发送的邮件的信息*/public boolean sendTextMail(MailSenderInfo mailInfo) {// 判断是否需要⾝份认证MyAuthenticator authenticator = null;Properties pro = mailInfo.getProperties();if (mailInfo.isValidate()) {// 如果需要⾝份认证,则创建⼀个密码验证器authenticator = new MyAuthenticator(mailInfo.getUserName(), mailInfo.getPassword());}// 根据邮件会话属性和密码验证器构造⼀个发送邮件的sessionSession sendMailSession = Session.getDefaultInstance(pro, authenticator);try {// 根据session创建⼀个邮件消息Message mailMessage = new MimeMessage(sendMailSession);// 创建邮件发送者地址Address from = new InternetAddress(mailInfo.getFromAddress());// 设置邮件消息的发送者mailMessage.setFrom(from);// 创建邮件的接收者地址,并设置到邮件消息中Address to = new InternetAddress(mailInfo.getToAddress());mailMessage.setRecipient(Message.RecipientType.TO, to);// 设置邮件消息的主题mailMessage.setSubject(mailInfo.getSubject());// 设置邮件消息发送的时间mailMessage.setSentDate(new Date());// 设置邮件消息的主要内容String mailContent = mailInfo.getContent();mailMessage.setText(mailContent);Transport.send(mailMessage);return true;} catch (MessagingException ex) {ex.printStackTrace();}return false;}/*** 以HTML格式发送邮件** @param mailInfo* 待发送的邮件信息*/public static boolean sendHtmlMail(MailSenderInfo mailInfo) {// 判断是否需要⾝份认证MyAuthenticator authenticator = null;Properties pro = mailInfo.getProperties();// 如果需要⾝份认证,则创建⼀个密码验证器if (mailInfo.isValidate()) {authenticator = new MyAuthenticator(mailInfo.getUserName(), mailInfo.getPassword()); }// 根据邮件会话属性和密码验证器构造⼀个发送邮件的sessionSession sendMailSession = Session.getDefaultInstance(pro, authenticator);try {// 根据session创建⼀个邮件消息Message mailMessage = new MimeMessage(sendMailSession);// 创建邮件发送者地址Address from = new InternetAddress(mailInfo.getFromAddress());// 设置邮件消息的发送者mailMessage.setFrom(from);// 创建邮件的接收者地址,并设置到邮件消息中Address to = new InternetAddress(mailInfo.getToAddress());// Message.RecipientType.TO属性表⽰接收者的类型为TOmailMessage.setRecipient(Message.RecipientType.TO, to);// 设置邮件消息的主题mailMessage.setSubject(mailInfo.getSubject());// 设置邮件消息发送的时间mailMessage.setSentDate(new Date());// MiniMultipart类是⼀个容器类,包含MimeBodyPart类型的对象Multipart mainPart = new MimeMultipart();// 创建⼀个包含HTML内容的MimeBodyPartBodyPart html = new MimeBodyPart();// 设置HTML内容html.setContent(mailInfo.getContent(), "text/html; charset=utf-8");mainPart.addBodyPart(html);// 将MiniMultipart对象设置为邮件内容mailMessage.setContent(mainPart);// 发送邮件Transport.send(mailMessage);return true;} catch (MessagingException ex) {ex.printStackTrace();}return false;}}2.邮件发送信息MailSenderInfopackage hk.buttonwood.ops.email;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;import java.util.Arrays;import java.util.Properties;import java.util.Vector;public class MailSenderInfo implements Serializable {// 发送邮件的服务器的IP和端⼝private String mailServerHost;private String mailServerPort = "25";private long uid;//唯⼀标⽰// 邮件发送者的地址private String fromAddress;// 邮件接收者的地址private String toAddress;// 登陆邮件发送服务器的⽤户名和密码private String userName;private String password;// 是否需要⾝份验证private boolean validate = false;private String filename="";private Vector file = new Vector(); //⽤于保存发送附件的⽂件名的集合 private String subject;// 邮件的⽂本内容private String content;// 邮件附件的⽂件名private String[] attachFileNames;//邮箱来源private int portfolio;//邮箱来源⽇期private String date;public void setUid(long uid) {this.uid = uid;}public long getUid() {return uid;}public void setDate(String date) {this.date = date;}public void setPortfolio(int portfolio) {this.portfolio = portfolio;}public String getDate() {return this.date;}public int getPortfolio() {return this.portfolio;}/*** 获得邮件会话属性*/public Properties getProperties(){Properties p = new Properties();p.put("mail.smtp.host", this.mailServerHost);p.put("mail.smtp.port", this.mailServerPort);p.put("mail.smtp.auth", validate ? "true" : "false");return p;}public String getMailServerHost() {return mailServerHost;}public void setFile(Vector file) {this.file = file;}public Vector getFile() {return this.file;}public void setFilename(String filename) {this.filename = filename;}public String getFilename() {return this.filename;}public void setMailServerHost(String mailServerHost) {this.mailServerHost = mailServerHost;}public String getMailServerPort() {return mailServerPort;}public void setMailServerPort(String mailServerPort) {this.mailServerPort = mailServerPort;}public boolean isValidate() {return validate;}public void setValidate(boolean validate) {this.validate = validate;}public String[] getAttachFileNames() {return attachFileNames;}public void setAttachFileNames(String[] fileNames) {this.attachFileNames = fileNames;}public String getFromAddress() {return fromAddress;}public void setFromAddress(String fromAddress) {this.fromAddress = fromAddress;}public String getPassword() {return password;public void setPassword(String password) {this.password = password;}public String getToAddress() {return toAddress;}public void setToAddress(String toAddress) {this.toAddress = toAddress;}public String getUserName() {return userName;}public void setUserName(String userName) {erName = userName;}public String getSubject() {return subject;}public void setSubject(String subject) {this.subject = subject;}public String getContent() {return content;}public void setContent(String textContent) {this.content = textContent;}public Object deepCopy() throws Exception{// 将该对象序列化成流,因为写在流⾥的是对象的⼀个拷贝,⽽原对象仍然存在于JVM⾥⾯。
电子邮件的使用实训报告

一、实训背景随着信息技术的飞速发展,电子邮件已经成为人们日常生活和工作中不可或缺的通讯工具。
为了提高我的信息技术应用能力,更好地适应社会发展的需求,我参加了本次电子邮件使用实训。
本次实训旨在通过实际操作,掌握电子邮件的基本功能和使用技巧,提高电子邮件的写作和发送效率。
二、实训内容1. 电子邮件的基本功能(1)注册邮箱账号首先,我选择了国内知名的邮箱服务商——网易邮箱,注册了一个个人邮箱账号。
在注册过程中,我按照提示填写了基本信息,并设置了密码和邮箱昵称。
(2)登录邮箱注册成功后,我使用账号和密码登录邮箱,进入邮箱主界面。
主界面分为收件箱、发件箱、草稿箱、垃圾箱等模块,方便用户管理邮件。
(3)撰写邮件在发件箱中,我点击“写邮件”按钮,进入撰写邮件界面。
在此界面,我可以填写收件人、主题、正文等内容。
同时,还可以添加附件、设置邮件格式等。
(4)发送邮件完成邮件撰写后,点击“发送”按钮,邮件即可成功发送。
在发送过程中,我了解到邮件发送速度与网络环境、邮件大小等因素有关。
2. 电子邮件的使用技巧(1)提高邮件发送速度在撰写邮件时,尽量简洁明了,避免冗长的内容。
此外,合理设置邮件大小,不超过邮箱服务商的限制,可以加快邮件发送速度。
(2)提高邮件阅读体验在撰写邮件时,注意使用分段、加粗、斜体等格式,使邮件内容更易于阅读。
同时,合理使用图片、链接等元素,增强邮件的吸引力。
(3)防止邮件被误删定期清理邮箱,将重要的邮件归类保存。
同时,为重要邮件设置“标记”或“加星”等标记,以便于查找。
(4)提高邮件安全性在设置邮箱密码时,使用复杂且不易被破解的密码。
此外,开启邮箱的“登录保护”功能,防止他人非法登录。
三、实训收获通过本次电子邮件使用实训,我收获颇丰:1. 掌握了电子邮件的基本功能和使用技巧,提高了自己的信息技术应用能力。
2. 了解了电子邮件在日常生活和工作中的重要作用,为今后的学习和工作打下了坚实基础。
3. 认识到电子邮件的安全性至关重要,学会了如何保护自己的邮箱账户。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
进程通信实验报告一、实验名称:进程通信二、实验目的:掌握用邮箱方式进行进程通信的方法,并通过设计实现简单邮箱理解进程通信中的同步问题以及解决该问题的方法。
三、实验原理:邮箱机制类似于日常使用的信箱。
对于用户而言使用起来比较方便,用户只需使用send ()向对方邮箱发邮件 receive ()从自己邮箱取邮件, send ()和 receive ()的内部操作用户无需关心。
因为邮箱在内存中实现,其空间有大小限制。
其实send ()和 receive ()的内部实现主要还是要解决生产者与消费者问题。
四、实验内容:进程通信的邮箱方式由操作系统提供形如send ()和receive ()的系统调用来支持,本实验要求学生首先查找资料了解所选用操作系统平台上用于进程通信的系统调用具体形式,然后使用该系统调用编写程序进行进程间的通信,要求程序运行结果可以直观地体现在界面上。
在此基础上查找所选用操作系统平台上支持信号量机制的系统调用具体形式,运用生产者与消费者模型设计实现一个简单的信箱,该信箱需要有创建、发信、收信、撤销等函数,至少能够支持两个进程互相交换信息,比较自己实现的信箱与操作系统本身提供的信箱,分析两者之间存在的异同。
五、背景知识介绍:1、sembuf 数据结构struct sembuf{unsigned short int sem_num; //semaphore numbershort int sem_op; //semaphore operationshort int sem_flg; //operation flag};sem_num :操作信号在信号集中的编号,第一个信号的编号是0。
进程A 进程B 信箱A 信箱B Send()Send() receive() receive()sem_op:如果其值为正数,该值会加到现有的信号内含值中。
通常用于释放所控资源的使用权;如果sem_op的值为负数,而其绝对值又大于信号的现值,操作将会阻塞,直到信号值大于或等于sem_op的绝对值。
通常用于获取资源的使用权;如果sem_op的值为0,则操作将暂时阻塞,直到信号的值变为0。
sem_flg:信号操作标志,可能的选择有两种IPC_NOWAIT //对信号的操作不能满足时,semop()不会阻塞,并立即返回,同时设定错误信息。
IPC_UNDO //程序结束时(不论正常或不正常),保证信号值会被重设为semop()调用前的值。
这样做的目的在于避免程序在异常情况下结束时未将锁定的资源解锁,造成该资源永远锁定。
2、 semop函数函数原型:int semop(int semid, struct sembuf *sops, unsigned nsops);参数说明:semid:信号集的识别码,可通过semget获取。
sops:指向存储信号操作结构的数组指针。
nsops:信号操作结构的数量,恒大于或等于1。
返回说明:成功执行时,两个系统调用都返回0。
失败返回-1,错误信息保存在errno中。
3、semget函数函数原型:int semget(key_t key,int nsems,int semflg);参数说明:key:关键字值一般是由系统调用ftok()返回的nsems:指出了一个新的信号量集中应该创建的信号量的个数semflg:打开和存取操作与参数semflg中的内容相关。
返回说明:如果成功,则返回信号量集的IPC标识符。
如果失败,返回-1,错误信息保存在errno中。
4、semctl函数函数原型:int semctl(int semid,int semnum,int cmd,union semun arg);参数说明:senid:关键字值semnum:信号量数目cmd:要操作的具体命令arg:semnu的一个联合类型的副本。
返回说明:返回值:如果成功,则为一个正数。
如果失败,则为-1。
错误信息保存在errno 中。
5、pthread_create函数函数原型:int pthread_create(pthread_t *restrict tidp,const pthread_attr_t*restrict attr,void*(*start_rtn)(void*),void *restrict arg);参数说明:tidp:指向线程标识符的指针。
attr:用来设置线程属性。
第三个参数是线程运行函数的起始地址。
arg:运行函数的参数。
六、设计方案:1、定义两个数组当作两个邮箱int a_buf[5],b_buf[5];邮箱的容量为5。
2、定义两个指针指向邮箱的顶部int a_buf_top=0,b_buf_top=0;初始时邮箱都为空3、定义semaphore_P和semaphore_V两个函数实现P.V原语操作,用P.V原语实现进程的互斥。
4、定义发送和接收信息的函数,其中void * A_Send(void *arg)为A发送信息,void * B_Send(void *arg)为B发送信息,void *A_Receive(void *arg)为A接收信息;void*B_Receive(void *arg)为B接收信息。
5、调用创建线程函数,让上述四个函数并行运行。
七、预计的实验结果:A_Receive()和 B_Receive()分别接收B_Send()和 A_Send()发出的信息,发送的信息和接受的信息应该一样。
八、关键代码的分析:/***************************************** P原语操作* *************************************/int semaphore_P(int sem_id){struct sembuf p;p.sem_num=0;p.sem_op=-1;p.sem_flg=SEM_UNDO;if(semop(sem_id,&p,1)==-1){printf(errno);return 0;}return 1;}/**************************************** V原语操作* **********************************/int semaphore_V(int sem_id){struct sembuf v;v.sem_num=0;v.sem_op=1;v.sem_flg=SEM_UNDO;if(semop(sem_id,&v,1)==-1){printf(errno);return 0;}return 1;}/**************************************** A向B发送信息* ************************************/void * A_Send(void *arg){int i;for(i=0;i<10;i++){semaphore_P(sem_idAs); //P操作semaphore_P(a_mutex_semaphore); //互斥int number=rand(); //随机数为发送的邮件printf("A send to B:%d\n",number);b_buf[b_buf_top]=number;//邮箱B中接收A发送的邮件b_buf_top+=1;//A向B发送邮件,B的邮件数量加一semaphore_V(a_mutex_semaphore); //互斥semaphore_V(sem_idBr);//V操作sleep(1);}}九、调试记录:于pthread库不是Linux系统默认的库,连接时需要使用库libpthread.a, 所以在使用pthread_create创建线程时,在编译中要加-lpthread参数 gcc -w -lpthread semaphore.c十、实际的实验结果:ada@ada-desktop:~/OS$ gcc -w -o semaphore -lpthread semaphore.cada@ada-desktop:~/OS$ ./semaphoreB send to A:123A receive from B:123A send to B:222B receive from A: 222B send to A:111A receive from B:111A send to B:12334B receive from A: 12334ada@ada-desktop:~/OS$十一、实验结果分析:四个线程并发运行, A_Send()和 B_Send()发出信息,同时打印出发出的信息内容;A_Receive()和 B_Receive()分别接收B_Send()和 A_Send()发出的信息,并打印出接受的信息内容。
发出的内容和接收的内容一样,符合时间情况。
十二、附代码#include<unistd.h>#include<stdlib.h>#include<stdio.h>#include<pthread.h>#include<semaphore.h>#include<sys/types.h>#include<sys/ipc.h>#include<sys/sem.h>#include<errno.h>int a_buf[5],b_buf[5]; //邮箱的容量为5int a_buf_top=0,b_buf_top=0;//假设初始时邮箱都为空int sem_idAs,sem_idBs; //例如sem_idAs代表A此时最多可以向B发送的邮件数int sem_idAr,sem_idBr; //例如sem_idAr代表A此时邮箱中受到的邮件数int a_mutex_semaphore,b_mutex_semaphore; //互斥信号量/***************************************** P原语操作* *************************************/int semaphore_P(int sem_id)struct sembuf p;p.sem_num=0;p.sem_op=-1;p.sem_flg=SEM_UNDO;if(semop(sem_id,&p,1)==-1){printf(errno);return 0;}return 1;}/**************************************** V原语操作* **********************************/int semaphore_V(int sem_id){struct sembuf v;v.sem_num=0;v.sem_op=1;v.sem_flg=SEM_UNDO;if(semop(sem_id,&v,1)==-1){printf(errno);return 0;}return 1;}/**************************************** A向B发送信息* ************************************/void * A_Send(void *arg){int i;for(i=0;i<10;i++){semaphore_P(sem_idAs); //P操作semaphore_P(a_mutex_semaphore); //互斥int number=rand(); //随机数为发送的邮件printf("A send to B:%d\n",number);b_buf[*b_top] = num++;//邮箱B中接收A发送的邮件,(*b_top)+=1;//A向B发送邮件,B的邮件数量加一semaphore_V(a_mutex_semaphore); //互斥semaphore_V(sem_idBr);//V操作sleep(1);}}/***************************************** A接收B的信息* ***************************************/void *A_Receive(void *arg){int i;for( i=0;i<10;i++ ){semaphore_P(sem_idAr);//P操作semaphore_P(b_mutex_semaphore);//互斥a_buf_top-=1;//A接收B发送邮件,A的邮件数量减一printf("A receive from B:%d\n",a_buf[a_buf_top]);semaphore_V(b_mutex_semaphore); //互斥semaphore_V(sem_idBs);//V操作sleep(1);}}/**************************************** B向A发送信息* ************************************/void *B_Send(void *arg){int i;for(i=0;i<10;i++){semaphore_P(sem_idBs);semaphore_P(b_mutex_semaphore);int number=rand();printf("B send to A:%d\n",number);a_buf[a_buf_top]=number;a_buf_top+=1;semaphore_V(b_mutex_semaphore);semaphore_V(sem_idAr);sleep(1);}}/***************************************** B接收A的信息* ***************************************/void *B_Receive(void *arg){int i;for( i=0;i<10;i++){semaphore_P(sem_idBr);semaphore_P(a_mutex_semaphore);b_buf_top-=1;printf("B receive from A: %d\n",b_buf[b_buf_top]);semaphore_V(a_mutex_semaphore);semaphore_V(sem_idAs);sleep(1);}}int main(){/*创建线程1*/pthread_t thread1;pthread_t thread2;pthread_t thread3;pthread_t thread4;/*创建信号量*/if( (sem_idAs=semget( (key_t)1,1,IPC_CREAT|0660) )==-1 ) return 1;if( (sem_idBs=semget( (key_t)2,1,IPC_CREAT|0660) )==-1 ) return 1;if( (sem_idAr=semget( (key_t)3,1,IPC_CREAT|0660) )==-1 ) return 1;if( (sem_idBr=semget( (key_t)4,1,IPC_CREAT|0660) )==-1 ) return 1;if( (a_mutex_semaphore=semget( (key_t)5,1,IPC_CREAT|0660) )==-1 ) return 1;if( (b_mutex_semaphore=semget( (key_t)6,1,IPC_CREAT|0660) )==-1 ) return 1;/*控制信号队列的运作*/semctl(sem_idAs,0,SETVAL,0);semctl(sem_idBs,0,SETVAL,0);semctl(sem_idAr,0,SETVAL,0);semctl(sem_idBr,0,SETVAL,0);semctl(a_mutex_semaphore,0,SETVAL,1);semctl(b_mutex_semaphore,0,SETVAL,1);//调用四个线程,让四个函数并行运行pthread_create(&thread1, NULL, A_Send, NULL);pthread_create(&thread2, NULL, B_Send, NULL);pthread_create(&thread3, NULL, A_Receive, NULL);pthread_create(&thread4, NULL, B_Receive, NULL);sleep(60);//保证主程序退出之前邮箱操作已经完成return 0;}。