socket编程实验.docx
- 文档编号:12505743
- 上传时间:2023-06-06
- 格式:DOCX
- 页数:17
- 大小:202.57KB
socket编程实验.docx
《socket编程实验.docx》由会员分享,可在线阅读,更多相关《socket编程实验.docx(17页珍藏版)》请在冰点文库上搜索。
socket编程实验
计算机通信网络实验
socket编程实验
学院:
班级:
学号:
姓名:
2012年11月4日
一、实验目的
熟练掌握socket编程命令
二、实验内容
1.简单的客户机/服务器程序的实现
2.使用套接字接口在TCP连接上发送消息
3.还用到了其他的UNIX网络功能
4.该应用允许用户在一端的机器上输入并把文本发送给另一端机器的用户
5.它是UNIX中talk的一个简化版本,类似于WEB聊天室的核心程序。
客户端
1)客户端使用远端的机器名作为参数
2)它调用UNIX程序gethostbyname把该名字转化为远端主机的IP地址。
3)接着构造套接字接口所需的地址数据结构(sin)。
这个数据结构表明我们将一直用套接字与因特网(AF_INET)连接。
在这个例子中,我们用TCP端口号5432作为共知的服务器端口号;它恰好不是分配给其他因特网服务的端口号。
建立连接的最后一步是调用socket和connect。
一旦connect操作返回,建立起连接,客户程序将进入主循环,不断从标准输入读文本并通过套接字发送。
服务器
服务器的实现也很简单:
1)填上自己的端口号(SERVER_PORT)构造地址数据结构。
它并不指明IP地址,从而使应用程序可以接受来自本地任一IP地址的连接。
2)服务器执行与被动打开有关的初始步骤:
建立一个套接字,将它绑定到本地地址
设置允许同时连接的最大数。
3)主循环等待远端主机试图与之连接,当远端有一台主机试图与之连接时,它就接收并输出连接上送来的字符。
sockets编程基础知识
网络编程就是通过计算机网络与其他程序进行通信的程序,socket编程是网络编程的主流工具。
socketAPI是实现进程间通信的一种编程设施,也是一种为进程间提供底层抽象的机制。
尽管应用开发人员很少需要在该层编写代码,但是理解socketAPI还是非常重要的。
主要有两点原因:
第一,高层设施是构建于socketAPI之上的,它们是利用socketAPI提供的操作来实现。
第二,对于响应时间要求较高或运行于有限资源平台上的应用,甚至socketAPI是唯一可用的进程间通信设施。
应用程序通信方式
socketAPI出现于20世纪80年代早期,作为BerkeleyUnix(BSD4.2)操作系统程序库来通过进程间通信功能。
现在主流操作系统都提供socketAPI。
在基于Unix系统中,如BSD、Linux系统,socketAPI是操作系统内核的一部分。
在MS-DOS、WindowsOS、OS/2等操作系统中,socketAPI是以程序库形式提供的,如在Windows系统中,socketAPI被称为Winsock。
Socket接口规范可以适用多种通讯协议。
主要是TCP/IP。
TCP/IP是计算机互联最常适用的网络通讯协议。
TCP/IP的核心部分由网络操作系统的内核实现,应用程序通过编程接口来访问TCP/IP。
TCP/IP使用一个网络地址和一个服务端口号来惟一地标识设备。
网络地址标识网络上的特定设备。
端口号标识要连接到的该设备上的特定服务。
网络通讯的基本模式是:
1)每一台通讯的主机都有一个本网络环境中惟一的IP地址
2)一台主机上往往有多个通讯程序存在,每个这样的程序都要占用一个通讯端口
因此,一个IP地址,一个通讯端口,就能确定一个通讯程序的位置。
基于C的socket编程相关数据结构
1.sockaddr结构
structsockaddr
{
unsignedshortsa_family;
/*地址族,AF_xxx有IPV4与IPV6等*/
charsa_data[14];
/*14字节的协议地址*/
};
sa_family一般为AF_INET,表示Internet协议族,如是AF_UNIX表示UNIX协议簇;
sa_data中包含该socket的IP地址和端口号。
2.in_add结构
in_add结构可用来存储四字节的IP地址
structin_addr{
unsignedlongs_addr;
};
3.sockaddr_in结构
structsockaddr_in
{
shortintsin_family;/*地址族*/
unsignedshortintsin_port;/*端口号*/
structin_addsin_addr;/*IP地址*/
unsignedcharsin_zero[8];
/*填充0以保持与structsockaddr同样大小*/
};
该结构中sin_zero使得sockaddr和sockaddr_in指针类型相互转换;
sin_port和sin_addr必须是网络字节顺序,因为它们被封装在包的IP和UDP层,sin_family不发送到网络上可以是本机字节顺序。
基于C的socket编程相关函数
1.socket()函数
该函数用于根据指定的地址族、数据类型和协议来分配一个套接字的描述字及其所用的资源。
socket函数原型为:
intsocket(intdomain,inttype,intprotocol);
a、参数domain指定地址描述,一般为AP_INET;
b、参数type指定socket类型:
SOCK_STREAM和SOCK_DGRAM;
c、参数protocol通常为0;
d、函数返回值为一个整型socket描述符,在bind函数中调用。
2.bind()函数
该函数用于将一个本地地址与一个套接字绑定在一起。
intbind(intsockfd,structsockadd*my_addr,intaddrlen);
a、sockfd:
socket描述符,使用socket函数返回值,将该socket与本机上的一个端口相关联。
在设计服务器端程序是需要调用bind函数,以在该端口上监听服务请求;而客户端一般不需要调用bind函数,因为只需知道服务器IP地址,并不关心客户通过哪个端口与服务器建立连接,内核会自动选择一个未被占用的端口供客户端来使用。
b、my_addr:
指向包含本机IP地址及端口号等信息的sockaddr类型的指针。
c、addrlen:
sizeof(structsockaddr)的值。
d、bind函数返回值:
为-1表示遇到错误,并且errno中包含相应的错误码。
3.connect()函数
与远程服务器建立一个TCP连接。
intconnect(intsockfd,structsockaddr*serv_addr,intaddrlen);
a、sockfd:
目的服务器的socket描述符。
b、serv_addr:
指向包含目的服务器的IP地址及端口号的指针。
c、addrlen:
sizeof(structsockaddr)的值。
d、connect函数返回值:
为-1表示遇到错误,并且errno中包含相应的错误码,进行服务器端程序设计时不需调用connect函数。
4.listen()函数
在服务器端程序中,当socket与某一端口绑定后,需要监听该端口,及时处理到达该端口上的服务请求。
intlisten(intsockfd,intbacklog);
a、sockfd:
Socket系统调用返回的socket描述符。
b、backlog:
指定在请求队列中允许的最大请求数,进入的连接请求将在队列中等待接收backlog限制了队列中等待服务的请求数目,系统缺省值为20。
c、listen函数返回值:
为-1表示遇到错误,并且errno中包含相应的错误码。
5.accept()函数
当某个客户端试图与服务器监听的端口连接时,该连接请求将排队等待服务器用accept接收它并为其建立一个连接。
intaccept(intsockfd,structsockaddr*addr,int*addrlen);
a、sockfd:
被监听的socket描述符。
b、addr:
sockaddr类型的指针变量,用来存放提出连接请求服务的主机信息。
c、accept函数返回值为-1表示遇到错误,并且errno中包含相应的错误码
如果没有错误,accept()函数返回一个新想socket描述符,供这个新连接来实用,而服务器可以继续在以前的socket上监听,同时可以在新的socket描述符上进行数据发送和数据接收(sent()和recv()操作)。
6.sent()和recv()函数
用于在面向连接(TCP)的socket上进行数据传输
send()函数原型:
intsend(intsockfd,constvoid*msg,intlen,intflags);
a、sockfd:
用于传输数据的socket描述符。
b、msg:
是一个指向要发送数据的指针。
c、len:
以字节为单位的数据的长度。
d、flags:
一般情况下置为0。
e、函数返回值:
为-1表示遇到错误,并且errno中包含相应的错误码,否则返回所发送数据的总数,该数字可能小于len中所规定的大小。
7.endto()和recvfrom()函数
这两个函数是利用数据报方式(UDP)进行数据传输。
在无连接的数据报socket方式下,由于本地socket并没有与远程机器建立连接,所以在发送数据时应指明目的地址。
sendto()原型:
intsendto(intsockfd,constvoid*msg,intlen,unsignedintflags,conststructsockaddr*to,inttolen);
a、sockfd:
用于传输数据的socket描述符。
b、msg:
是一个指向要发送数据的指针。
c、len:
以字节为单位的数据的长度。
d、flags:
一般情况下置为0。
e、函数返回值:
为-1表示遇到错误,并且errno中包含相应的错误码,否则返回所发送数据的总数,该数字可能小于len中所规定的大小。
f、表示目的机器的IP地址和端口号。
g、tolen:
被赋值为sizeof(structsockaddr)。
recvfrom函数原型:
intrecv(intsockfd,void*buf,intlen,unsignedintflags,structsockaddr*from,intfromlen);
a、sockfd:
是接收数据的socket描述符。
b、buf:
是存放接收数据的缓冲区。
c、len:
以字节为单位的缓冲区的长度。
d、flags:
一般情况下置为0。
e、函数返回值:
为-1表示遇到错误,并且errno中包含相应的错误码,无错则返回读入的字节数,如果连接被中止,返回0。
f、from:
保存源机器的IP地址和端口号。
g、fromlen:
常被赋值为sizeof(structsockaddr)。
当对于数据报socket调用了connect()函数时,也可以用send()和recv()进行数据传输,但该socket仍然是数据报socket,并利用传输层的UDP服务。
但是在发送或接收数据报时,内核会自动为它加上目的地址和源地址信息。
8.close()和shutdown()函数
当所有的数据操作结束后,可以调用close函数来释放该socket资源,从而停止在该socket上的任何数据操作。
也可以调用shutdown函数,允许只停止在某个方向上的数据传输,而另一个方向上的数据传输继续进行。
例如可以关闭某一个socket上的写操作uo允许继续在该socket上接收数据,直到读入所有数据。
但是,shutdown函数并不关闭套接字所占用的所有资源,除非调用close函数来释放。
函数原型:
close(intsockfd);
shutdown(intsockfd,inthow);
how参数的值和含义:
0:
不允许继续接收数据;
1:
不允许继续发送数据;
2:
不允许继续发送和接收数据。
shutdown在操作成功时返回0,错误时返回-1,并置errno值。
9.字节顺序转换函数
htons():
HosttoNetworkShort的缩写,该函数将主机的无符合短整型数字节顺序转换成网络字节顺序。
htonl():
HosttoNetworkLong的缩写,该函数将主机的无符合长整型数字节顺序转换成网络字节顺序。
ntohs():
NetworktoHostShort的缩写,该函数将无符号短整型数从网络字节顺序转换为主机字节顺序。
ntohl():
NetworktoHostlong的缩写,该函数将无符号长整型数从网络字节顺序转换为主机字节顺序。
三、实验过程
服务器端操作socket(套接字):
1.在初始化阶段调用WSAStartup()
2、建立Socket
3、绑定端口
4、监听
5、服务器端接受客户端的连接请求
6、发送及接收信息
7、结束socket连接
相应的程序:
//***********************server.c*****************************
#include
#pragmacomment(lib,"ws2_32.lib")//WINSOCKAPI连接库文件
#include
#include
voidmain()
{
WORDwVersionRequested;
WSADATAwsaData;
interr;
intlen;
charrecvBuf[50];
charsendBuf[50];
SOCKETsockSrv;//用于服务器监听的Socket
SOCKADDR_INaddrSrv;//存放服务端套接字信息
SOCKADDR_INaddrClient;//存放连接上的客户端套接字信息
SOCKETnew_sock;//用于连接后新的socket
//************************初始化阶段******************************
wVersionRequested=MAKEWORD(1,1);//WinSocket1.1版本
err=WSAStartup(wVersionRequested,&wsaData);
//此函数在应用程序中初始化WindowsSocketsDLL,只有此函数调用成功后,才可以再调用其他WindowsSocketsDLL中的API函数
//wsaData用来存储系统传回的关于WinSocket的资料
if(err!
=0){//err=0就表示初始化成功
return;
}
if(LOBYTE(wsaData.wVersion)!
=1||HIBYTE(wsaData.wVersion)!
=1)
{
WSACleanup();
return;
}
//************************建立socket******************************
sockSrv=socket(AF_INET,SOCK_STREAM,0);
//调用Socket()函数在服务器建立监听的Socket,并定义此Socket所使用的通信协议。
//指定地址描述为AF_INET
//指定socket类型为SOCK_STREAM,建立的是遵从TCP/IP协议的socket
if(sockSrv==-1)return;//错误检查
//************************绑定端口******************************
addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
//设置服务器地址,INADDR_ANY表示使用自己的IP地址
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(6000);//设定端口为6000
if(bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR))==-1)return;//绑定端口并检查
//**************************监听********************************
if(listen(sockSrv,5)==-1)return;
//使服务器端的Socket进入监听状态,并设定可以建立的最大连接数为5
//**********************发送及接受消息**************************
len=sizeof(SOCKADDR_IN);//Socket的地址值的长度
while
(1)
{
new_sock=accept(sockSrv,(SOCKADDR*)&addrClient,&len);//接受客户端连接,获取客户端的ip地址
if(new_sock==-1)continue;
printf("gotconnectionfromclient:
%s\n-------Input\"exit\"todisconnectfromclient.-------\n",inet_ntoa(addrClient.sin_addr));//接受客户端连接,获取客户端的ip地址
printf("Server:
");
scanf("%s",sendBuf);//输入服务器要发送的消息,或者输入exit可断开连接
while(strcmp(sendBuf,"exit")!
=0){
send(new_sock,sendBuf,strlen(sendBuf)+1,0);//发送消息到客户端
recv(new_sock,recvBuf,50,0);//接受客户端消息
if(strcmp(recvBuf,"exit")==0)break;
printf("Client:
%s\nServer:
",recvBuf);
scanf("%s",sendBuf);//输入服务器要发送的消息,或者输入exit可断开连接
}
send(new_sock,"exit",5,0);//发送消息到客户端
printf("-------Thesessionisterminated!
------\n");
closesocket(new_sock);//断开连接
}
}
//**********************endofprogram************************
客户端操作socket(套接字):
1.在初始化阶段调用WSAStartup()
2、建立Socket
3、设置服务器地址及端口号
4、连接服务器
5、发送及接收信息
6、结束socket连接
#include
#include
#pragmacomment(lib,"ws2_32.lib")//WINSOCKAPI连接库文件
#include
voidmain()
{
WORDwVersionRequested;
WSADATAwsaData;//WSAata用来存储系统传回的关于WinSocket的资料。
interr;
SOCKETsockClient;
SOCKADDR_INaddrSrv;
charrecvBuf[50];
charsendBuf[50];
//************************初始化阶段******************************
wVersionRequested=MAKEWORD(1,1);//WinSocket1.1版本
err=WSAStartup(wVersionRequested,&wsaData);
//此函数在应用程序中初始化WindowsSocketsDLL,只有此函数调用成功后,才可以再调用其他WindowsSocketsDLL中的API函数
//wsaData用来存储系统传回的关于WinSocket的资料
if(err!
=0)return;
if(LOBYTE(wsaData.wVersion)!
=1||HIBYTE(wsaData.wVersion)!
=1)
{
WSACleanup();
return;
}
//*****************建立socket、发送、接受消息***********************
sockClient=socket(AF_INET,SOCK_STREAM,0);//AF_INET..tcp连接
//初始化连接与端口号
addrSrv.sin_addr.S_un.S_addr=inet_addr("222.25.162.196");//设置服务器地址
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(6000);//设置端口号
connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));//连接服务器
printf("-------gotconnectionfromserver.-------\n-------Input\"exit\"todisconnectfromserver.-------\n");
recv(sockClient,recvBuf,50,0);//接受数据
while(strcmp(recvBuf,"exit")!
=0){
printf("Server:
%s\nClient:
",recvBuf);
scanf("%s",sendBuf);//输入服务器要发送的消息
if(strcmp(sendBuf,"exit")==0){
send(sockClient,"exit",5,0);
break;
}
send(sockClient,sendBuf,strlen(sendBuf)+1,0);//发送数据
recv(sockClient,recvBuf,50,0);//接受数据
}
printf("-------Thesessionisterminated!
------\n");
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- socket 编程 实验