查看: 2712|回复: 3
打印 上一主题 下一主题

C语言也能干大事板书(11\13\18)

[复制链接]
跳转到指定楼层
沙发
发表于 2014-9-16 14:13:53 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 伊海 于 2014-9-16 14:25 编辑

Socket网络编程
板书11:
这节课是自己动手写QQ、自己动手写飞鸽传书的基础,以后想从事网络开发、信息系统开发、游戏开发、嵌入式系统开发等的同学必须学习。
演示一个简单的和网易Email服务器对话的过程。
1、网络基本概念
讲解QQ的基本原理
讲解浏览器上网的基本原理
服务器:Server。提供服务的计算机。
客户端:Client。和服务器端交互的一个设备。
IP地址:计算机在网络中的地址。相当于每个家庭的电话。211.97.1.2
别名、域名:www.RuPeng.com。域名就相当于你家的地址。问114,你家的电话(告诉地址)
DNS:网络中的114。Domain Name System。
端口:Port。不同的程序连接服务器时候用的插座。(程序和服务器通信的时候的一个开得的一个口子)
Socket(套接字):导线、网络连接。

2、WinSock、WinSocket。
Socket:平台无关的。Socket标准。所有操作系统都实现了这个标准。Send、recv。。。标准的。一通百通!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
WinSock:添加了一些Windows独有的函数。而且不用这些函数的话Socket程序还跑不起来。羞臊微软!!!
WinSock编程:平台无关,一通百通。WSA(WindowsSocket API)
Sz1.tencent.com
Sz2.tencent.com

3、LastError
调用WindowsAPI的时候,每步执行完毕都会把执行结果放到LastError中去,所以应该在函数执行完毕立即去取。

DeleteFile(f1)
DeleteFile(f2)
GetLastError()
LastError只能容纳一个错误码
DeleteFile(f1)
GetLastError()
DeleteFile(f2)
GetLastError()
错误码。2233、344555
FormatMessage:把错误码转换为错误消息。

Windows错误处理

GetLastError
  1. <p class="MsoNormal" style="margin-left: 18pt; text-indent: 0cm; line-height: 18.9pt;">
  2. </p>
复制代码

复制代码

在.h中声明函数,在.c中实现!!!

都会有哪些错误?
4、模板代码:
(1)添加winsock2.h
(2)连接库“wsock32”。怎么知道添加它呢?
(3)、模板代码
  1. WSADATA wsaData;
  2. //初始化Socket库
  3. WSAStartup(MAKEWORD(2,0),&wsaData);
  4. //创建一根电线
  5. SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  6. SOCKADDR_IN sa;
  7. sa.sin_family=AF_INET;
复制代码



QQ服务器的端口8888需要指定客户端的端口是9999.
端口有一个特点:排他性!端口已经被别的程序占用,不能再用这个端口。
开两个QQ。11111111111
22222222222 9999。如果端口可以被多个程序使用的话,QQ聊天服务器发过来的消息被多个QQ收到。很荒谬! 排他性!
如果在程序里写死了客户端用的端口。。。所以才需要Socket替客户端动态分配一个端口。所以不需要在程序中显示指定客户端的端口号!
客户端向服务器端发消息:send
服务器端想客户端发消息,客户端这边应该接收,recv。(receive)

SMTP服务器,你连上来以后服务器端主动向你发一条消息
recv(sock,buffer,256,0);
第一个是使用的socket,“导线”,套接字
接收数据的缓冲区的指针
接收数据的缓冲区的大小
  1. send(sock,cQuit,lstrlen(cQuit),0);
复制代码

第一个是使用的socket,“导线”,套接字
接收数据的缓冲区的指针
接收数据的缓冲区的大小
  1. //一上来人家就主动和你唠嗑:
  2. char buffer[256];
  3. ZeroMemory(buffer,sizeof(buffer)/sizeof(char));
  4. //接收问候语
  5. recv(sock,buffer,256,0);
  6.    MessageBox(hwnd,buffer,"",0);
  7. //朋友再见
  8. //注意不能忘了末尾的回车
  9. TCHAR cQuit[] = "QUIT\n";
  10. send(sock,cQuit,lstrlen(cQuit),0);
  11. ZeroMemory(buffer,sizeof(buffer)/sizeof(char));
  12. //接收GoodBye
  13. recv(sock,buffer,256,0);
  14. MessageBox(hwnd,buffer,"",0);
复制代码




回复

使用道具 举报

板凳
 楼主| 发表于 2014-9-16 14:20:14 | 只看该作者

板书13:Socket网络开发2
这节课是对上节课内容的复习和实战,并且融合了C语言中指针、函数、类型转换、结构体等知识。

一、复习:
复述QQ的基本原理;在一个典型的网络程序中分为哪两端?
IP地址、域名、DNS、端口是做什么用的?
演示一个简单的和网易Email服务器对话的过程。
Socket是Windows特有的吗?什么是WinSock?
WinSock和Socket标准的区别和联系。
Windows中函数的错误信息是通过什么来报告的?
创建客户端到服务器端的Socket连接的时候需要指定服务器端的端口吗?为什么?需要指定客户端的端口吗?为什么?客户端不用显式指定端口,但并不是说不需要端口,而是这个端口是由操作系统分配的。
有一个端口能同时被多个程序占用吗?
发送、接收数据各用什么函数?

二、开发网络定时器
1、看看Windows的网络授时功能(客户端)
2、网络授时原理
客户端连接到授时服务器上,授时服务器会马上将当前时间发送给客户端,原理很简单。
网络授时分为好几种协议,比如返回的是日期字符串,有的返回的是自1900年1月1日至今的秒数。“2009-03-0822:13:58”、39393933993
扩展阅读:http://zhidao.baidu.com/question/20121991.html
国家授时中心提供的网络授时返回的是自1900年1月1日至今的秒数。
3、先移植第一节课的代码
可供选择的授时服务器(不止这些):
www.time.ac.cn国家授时中心
Clock.sgi.comSGI
        Tick.mit.edu
麻省理工学院
Time.nist.gov
        NIST
几句话:
Compile:编译
Link:连接
       编译是单一的文件编译成.o.obj文件,然后Link.obj连接成.exe
Link库!!!!
一通百通的力量!!!!!!!!!!!!!!
C-Free、VC没有任何差别!!!!!!!!!!!!
小技巧:在命令提示符下不能CtrlC、CtrlV,但是选中后点右键就是复制、粘贴
4、授时服务器是37端口IPPORT_TIMESERVER。返回的是什么?
unsigned long ulTime;
recv(sock,(char *)&ulTime,sizeof(unsigned long),0);
深刻理解这段代码的含义
ulTime = ntohl(ulTime);
网络字节顺序转换为主机字节顺序。这个是重点,很多公司面试的时候都会问这个,以后工作中也会遇到。
什么是网络字节顺序、什么是主机字节顺序。
不同的CPU中处理整数的方式不一样,有的是低位在前、有的是高位在前。计算机组成原理、数字电路。。。
网络字节顺序则是统一标准。
如果直接接收的话就会造成接受者接收的数据正好是相反的。
扩展阅读:http://hi.baidu.com/cdmember_daihw/blog/item/ad83090f1fb4ffebab6457e6.html
中国是东8区。猜的:时间服务器返回的是格林尼治时间。

Windows中时间用SYSTEMTIME结构体表示时间,怎么将ulTime转换为SYSTEMTIME?网上找到下面的代码:
  1. #define HIGHTIME
  2. 21968699 // 21968708 // Jan 1, 1900 FILETIME.highTime
  3. #define LOWTIME
  4. 4259332096 // 1604626432 // Jan 1, 1900 FILETIME.lowtime
  5. SYSTEMTIME st;
  6. UINT64 uiCurTime, uiBaseTime, uiResult;
  7. uiBaseTime = ((UINT64) HIGHTIME << 32) + LOWTIME;
  8. uiCurTime = (UINT64)dwTime * (UINT64)10000000;
  9. uiResult = uiBaseTime + uiCurTime;
  10. FileTimeToSystemTime((LPFILETIME)&uiResult, &st);
复制代码
把它封装成函数,怎么设计接口?深刻理解指针以及Windows中LP的惯例。
把时间打印出来,怎么打印??????
怎么时间不对
设置系统时间
//SetSystemTime(&st);
作业:定时的进行网络对视。SetTimer函数,1分钟对时一次。时钟。

回复 支持 反对

使用道具 举报

地板
 楼主| 发表于 2014-9-16 14:24:45 | 只看该作者
板书18 对话框高级操作
板书:
1
、程序中打开新对话框,其实有代码可参考,WinMain。
  1. DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, Main_Proc);
复制代码
只要复制一份MainDlg.cpp和MainDlg.h改一下就行了
  1. DialogBox(hInstance, MAKEINTRESOURCE(IDD_MYDLG), NULL, Dlg1_Proc);
复制代码
怎么传递参数?使用DialogBoxParam函数,对比差别。
传入int;传入字符串;传入结构体。
传出。
怎样判断按下的按钮?通过返回值配合
怎么样在对话框关闭的时候把参数回传回去?
SetWindowLong设置的东西是和窗口的实例绑在一起的。什么是窗口实例?一个窗口打开两个、一个窗口打开两次(隐藏/打开、销毁/打开)。
  1. SetWindowLong(hwnd,GWL_USERDATA,(LPARAM)param);
复制代码

1
、在资源中插入新的对话框,并且调整控件
2
  1. HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE);
  2. DialogBox(hInstance, MAKEINTRESOURCE(IDD_LOGINDIALOG), NULL, Main_Proc);
复制代码

3
、每个对话框都有自己的一套MainDlg.cpp类似的代码,Main_Proc、Main_OnInitDialog等等
修改Main_Proc、Main_OnInitDialog等的前缀为LoginDlg_****,函数名不能重复
复制一份LoginDlg.h
#ifndef _MAIN_H
等也要修改

DialogBoxParam
parameter:
参数

#include "LoginDlg.h"

在OnInitDialog中处理传入参数,lParam就是传入的参数

通过DialogBoxParam来传入参数,在对话框中的***_OnInitDialog的LPARAM lParam来取参数。

long
类型,指针就是long了。
传递字符串

  1. TCHAR* buff = "abcd";
  2. DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_LOGINDIALOG), NULL, LoginDlg_Proc,(LPARAM)buff);//LoginDlg_Proc
复制代码

在对话框之间传字符串(指针)

  1. HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE);
  2. LoginData ld;
  3. ld.userName = "yzk";
  4. ld.password = "123456";
  5. //TCHAR* buff = "abcd";
  6. DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_LOGINDIALOG), NULL, LoginDlg_Proc,(LPARAM)&ld);//LoginDlg_Proc
  7. BOOL LoginDlg_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
  8. {
  9. LoginData* ld = (LoginData*)lParam;
  10. SetDlgItemText(hwnd,IDC_EDITUSERNAME,ld->userName);
  11. SetDlgItemText(hwnd,IDC_EDITPASSWORD,ld->password);
  12. return TRUE;
  13. }
复制代码

DialogBoxParam
默认是阻塞运行的
可以设置与窗口句柄关联的数据,SetWindowLong可以看做是把一些数据与窗口管理起来,“让它代为保管”
SetWindowLong
、GetWindowLong来在窗口中保存指针就可以了
只有一个文本框的对话框,有两个按钮【确定】、取消,允许对话框的使用者指定一个函数用来进行校验,能够校验值的正确性,如果不正确还会显示错误信息。提示:函数指针。
EndDialog(hwnd, 1);
在调用代码中通过DialogBoxParam的返回值就可以得到EndDialog设定的参数
不要重复同样的错误。不要忘了break。通过调试功能发现的问题。在怀疑的地方加断点调试
  1. LBN_DBLCLK:DoubleClick
  2. if(LBN_DBLCLK==codeNotify)
  3. {
  4. //MessageBox(hwnd,TEXT("双击"),TEXT(""),MB_OK);
  5. //LB_GETCURSEL消息

  6. int index = SendDlgItemMessage(hwnd,IDC_LIST1,LB_GETCURSEL,0,0);
  7. TCHAR buff[255];
  8. SendDlgItemMessage(hwnd,IDC_LIST1,LB_GETTEXT,index,(LPARAM)buff);
  9. MessageBox(hwnd,buff,TEXT(""),MB_OK);
  10. }
复制代码

课后作业:允许用户定制校验策略的InputDialog
2、Codenotify=LBN_DBLCLK 用户双击列表框中的字符串。

  1. if(LBN_DBLCLK==codeNotify)
  2. {
  3. int index = SendDlgItemMessage(hwnd,IDC_LIST1,LB_GETCURSEL,0,0);
  4. TCHAR buff[255];
  5. SendDlgItemMessage(hwnd,IDC_LIST1,LB_GETTEXT,index,(LPARAM)buff);
  6. MessageBox(hwnd,buff,TEXT(""),MB_OK);
  7. }
复制代码
3
、LBN_SELCHANGE



回复 支持 反对

使用道具 举报

4#
发表于 2014-9-16 17:21:53 | 只看该作者
点评  :  好长好长好长
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 加入因仑

本版积分规则

快速回复 返回顶部 返回列表