computer networks b-k8凯发旗舰
|
|
|
教学公告
一、client/server网络编程模型:
client/server网络编程基于socket编程基础,socket(套接字编程)源于unix,想深入学习的同学可以查找相关的资料进行学习。
windows socket编程思想也是源于unix socket,相关的函数都是直接拿过来用,只有部分的变量定义有些区别。套接字有两种类型:
流式套接字(sock_stream),基于tcp传输协议,面向连接,可靠的传输方式。
数据报式套接字(sock_dgram),基于udp,面向无连接,不可靠。
下面是关于tcp、udp socket编程的流程图:
tcp:
udp:
在windows上进行socket编程,需要引入相关的库文件:
#include
相关函数讲解:
加载套接字库并进行版本协商
int wsastartup(word wversionrequested,
//请求的版本号,低字节代表主版本,高字节代表副版本,一般我们用makeword(x,y)//宏来指定版本号,如:makeword(2,1)代表2.1的版本
lpwsadata lpwsadata
//out,一个wsadata结构体指针,用于接收实际加载的套接字 库版本号
)
创建套接字
socket socket(int af, //指定协议族,也即网际域,对于windows平台总是af_inet 或 pf_inet
int type,//指定要创建的套接字类型
int protocol//指定协议类型,我们一般设为0,让他根据我们前两个参数自动设置
)
绑定到本机地址和端口
int bind(socket s, //已创建的套接字描叙符
const struct sockaddr far *name, //要绑定的本机地址信息
int namelen //第二个参数的长度
)
其中要注意第二个参数,由于第二个参数适用于所有网络协议,所以我们可以根据需要进行替换,如我们常常这样定义一个af_inet 的地址信息:
sockaddr_in srvaddr;
srvaddr.family=af_inet;
srvaddr.port=hotns(666); //其中666代表端口号
srvaddr.sin_addr.s_un.s_addr=htonl(192.168.1.101);
//或srvaddr.sin_addr.s_un.s_addr=inaddr_any;(指绑定到本机的任一快网卡上,并且////其本身就是网络字节序,故无需转换,我推荐这种写法)
inet_addr和inet_ntoa函数
unsigned long inet_addr(sconst char far * cp);
inet_addr可以把一个点分十进制表示的ip(如:192.168.1.101)转换为unsinged long 类型的数据,且该返回值可以直接赋值给s_addr
char far * inet_ntoa(struct in_addr in);
inet_ntoa 从他函数的声明就知道他完成一个和inet_addr相反的转换 。
将指定的套接字设为见听听模式
int listen(socket s,int backlog);
第一个参数 s: 已经创建的套接字描述符
第二个参数 backlog 设置等待连接队伍的最大长度,注意:不是一个端口上可以同时连接的数目。
accept函数
就收客服端发送的连接请求
socket accept(
socket s,
struct sockaddr far * addr,// 返回请求连接方的ip和端口信息
int far * addrlen
);
send函数
通过一个已经建立连接的套接字发送数据
int send(
socket s,//注意:是以建立连接的套接字
const char far * buf,//目的地ip和端口信息
int len,
int falgs//该设置影响发送行为,我们一般设为0
)
recv 函数
int recv(
socket s,
char far *buf,//发送数据的缓存地址
int len,//发送数据长度
int flags//该设置影响发送行为,我们一般设为0
)
connect 函数
和一个特定的套接字建立连接
int connect(
socket s,
const struct sockaddr far * name,//目的地址信息
int namelen
)
recvfrom函数
接受一次数据并保存数据源地址信息
int recvfrom(
socket s,
char far*buf,
int len,
int flags,
struct sockaddr far* from//用于保存数据源地址信息
int far* fromlen
);
注意:最后一个参数是in,out类型,我们要在传参之前赋初始值
如:int len=sizeof(sockaddr);
sendto函数
向以一个特定的目的方发送数据
int sendto(
socket s,
const char far * buf,//要发送的数据
int len,//数据长度
int flags,
connect struct sockaddr far * to,//目的地址信息
int tolen
)
二、编程要求:
客户端ping服务器端,服务器端显示客户端发送数据的时间戳(如19:00:32),然后给客户端响应消息(pong)(可以随便是什么消息),客户端接收响应并输出,并显示时间时延,比如:延时5s。
客户端:
输入: ping 127.0.0.1
输出: ping success or ping failed.
服务端发送的消息
延时:xx s
服务端:
显示客户端发送的消息(时间戳):
如:客户端发送数据的时间为19:00:32
pingserver.c
//#include "stdafx.h"
#include
#include
#include
#include
#pragma comment()
//处理客户端发送的数据并响应
int pingserver()
{
//创建套接字
//绑定ip和端口
//开始监听
//循环接收数据
//接收数据
//打印客户端发送的数据,显示时间戳
//发送数据
}
int main(int argc, char* argv[])
{
pingserver();
return 0;
}
pingclient.c
// pingclient.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
//#include "stdafx.h"
#include
#include
#include
#include
#include
#pragma comment
#define maxn 1024
//#define ip_address "1"
//客户端ping程序,socket编程流程
int pingclient()
{
//得到服务器的地址
char *serverip = getserverip(strserverip);
//连接服务器的ip地址
//得到发送的数据,要求发送的数据为客户端的时间戳
getsenddata(senddata); //process sending data
//cout << senddata;
//发送
send(sclient, senddata, strlen(senddata), 0);
//接受
int ret = recv(sclient, recdata, 255, 0);
//得到接受时间
t2 = getcurrenttime();
//得到服务器端发送的数据,打印数据接收的时
int main(int argc, char* argv[])
{
pingclient();
return 0;
}