实验报告实验名称--SOCKET编程一、实验目的(1)加深对TCP和UDP的理解;(2)实现两台计算机之间TCP/UDP通信。
二、实验过程原理:socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用以实现进程在网络信。
如下图所示:TCP通信原理如图:代码:服务器端:#pragma comment(lib, "WS2_32.lib")#include<Winsock2.h>#include<iostream>#include<stdlib.h>using namespace std;int main(){int i=0;WSADATA wsaData;SOCKET oldSocket,newSocket;//客户地址长度int iLen=0;//发送的数据长度int iSend=0;//接收的数据长度int ircv =0;//处世要发送给客户的信息char buf[20]="I am a server";//接收来自用户的信息char fromcli[512];//客户和服务器的SOCKET地址结构struct sockaddr_in ser,cli;if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0){cout<<"failed to load winsock"<<endl;return 0;}cout<<"server waiting"<<endl;cout<<"---------------"<<endl;//创建服务器端帧听SOCKEToldSocket=socket(AF_INET,SOCK_STREAM,0);if(oldSocket==INVALID_SOCKET){cout<<"socket() failed:"<<WSAGetLastError()<<endl;return 0;}//以下是建立服务器端的SOCKET地址结构ser.sin_family=AF_INET;ser.sin_port=htons(5050);//使用系统指定的ip地址INADDR_ANY// ser.sin_addr.s_addr=htonl(INADDR_ANY);ser.sin_addr.s_addr= inet_addr("192.168.8.58");if(bind(oldSocket,(LPSOCKADDR)&ser,sizeof(ser))==SOCKET_ERROR) {cout<<"bind() failed:"<<WSAGetLastError()<<endl;return 0;}//进入侦听状态if(listen(oldSocket,5)==SOCKET_ERROR){cout<<"listen() failed:"<<WSAGetLastError()<<endl;return 0;}//接收客户端的连接iLen=sizeof(cli);newSocket=accept(oldSocket,(struct sockaddr*)&cli,&iLen);//产生一个新的SOCKETif(newSocket==INVALID_SOCKET){cout<<"accept() failed:"<<WSAGetLastError()<<endl;//return 0;}//进入一个无限循环,等待客户发送数据while(1){i++;//服务器初始化接收缓冲区memset(fromcli,0,512);ircv=recv(newSocket,fromcli,sizeof(fromcli),0);if(ircv==SOCKET_ERROR){cout<<"rcv() failed:"<<WSAGetLastError()<<endl;break;}else if(ircv==0)break;else {cout<<"-----服务器接收的容为--------"<<fromcli<<endl;}if(strcmp(fromcli,"quit")==0)break;}closesocket(newSocket);closesocket(oldSocket);WSACleanup();}客户端:#pragma comment(lib, "WS2_32.lib")#include<winsock2.h>#include<iostream>#include<stdio.h>using namespace std;#define DATA_BUFFER 512int main(){WSADATA wsaData;SOCKET sClient;char ch;int i=0;char *Serip="192.168.8.58";//随着程序所在主机的地址改变而改变int SeriPort=5050;//从服务器接收的数据的长度int iLen;//发送的数据长度int isnd;//接收缓冲区char buf[DATA_BUFFER];//发送缓冲区char sndbuf[DATA_BUFFER];//服务器端SOCKET地址结构struct sockaddr_in ser;//接收/发送缓冲区的初始化memset(buf,0,sizeof(buf));memset(sndbuf,0,DATA_BUFFER);if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0){cout<<"failed to load winsock"<<endl;return 0;}//填写要连接的服务器地址信息ser.sin_family=AF_INET;ser.sin_port=htons(SeriPort);ser.sin_addr.s_addr=inet_addr(Serip);//建立客户端字节流式套接字sClient=socket(AF_INET,SOCK_STREAM,0);if(sClient==INVALID_SOCKET){cout<<"socket() failed :"<<WSAGetLastError()<<endl;return 0;}//请求与服务器建立连接// cout<<"set link";if(connect(sClient,(struct sockaddr *)&ser,sizeof(ser))==INVALID_SOCKET){cout<<"connect() failed: "<<WSAGetLastError()<<endl;return 0;}else{//向服务器端发送数据while(1){cout<<endl;i++;cout<<"第"<<i<<"发送"<<endl;cin>>sndbuf;isnd=send(sClient,sndbuf,sizeof(sndbuf),0);if(isnd==0)return 0;else if(isnd==SOCKET_ERROR){cout<<"send() failed:"<<WSAGetLastError()<<endl;return 0;}cout<<"-----客户端发送容为----"<<sndbuf<<endl;}}closesocket(sClient);WSACleanup();}本机上客户端与服务器端通信结果如图:在两台服务器上分别运行服务器端和客户端,结果如图:UDP通信原理如图:代码:服务器端:#include "stdafx.h"#include <winsock2.h>#include <stdio.h>#include <stdlib.h>#define buffer_length 512#pragma comment(lib, "WS2_32.lib")void main(){WSADATA wsadata;SOCKET sSocket;int ilen;int irecv;char recv_buf[buffer_length];char send_buf[buffer_length];//服务器和客户SOCKET地址结构struct sockaddr_in seradd,cliadd;if(WSAStartup(MAKEWORD(2,2),&wsadata)!=0){printf("failed to load winsocket\n");return;}sSocket=socket(AF_INET,SOCK_DGRAM,0);if(sSocket==INVALID_SOCKET){printf("socket() failed:%d\n",WSAGetLastError());return;}//初始化服务器SOCKET地址结构seradd.sin_family=AF_INET;seradd.sin_port=htons(6666);//seradd.sin_addr.s_addr=htonl(INADDR_ANY);seradd.sin_addr.s_addr= inet_addr("0.0.0.0");if(bind(sSocket,(LPSOCKADDR)&seradd,sizeof(seradd))==SOCKET_ERR OR){printf("地址绑定时出错:%d\n",WSAGetLastError());int rua;scanf("%d", &rua);return;}ilen=sizeof(cliadd);//初始化接收缓冲区memset(recv_buf,0,sizeof(recv_buf));irecv=recvfrom(sSocket,recv_buf,buffer_length,0,(structsockaddr*)&cliadd,&ilen);if(irecv==SOCKET_ERROR){printf("接收出错%d\n",WSAGetLastError());int rua;scanf("%d", &rua);return;}else if(irecv==0)return;else{printf("\n%s--",recv_buf);printf("Server received from Client ip:[%s],port:[%d]\n",inet_ntoa(cliadd.sin_addr),ntohs(cliadd.sin_port));}while(1){//在此函数中cli为传出参数irecv=recvfrom(sSocket,recv_buf,buffer_length,0,(structsockaddr*)&cliadd,&ilen);if(irecv==SOCKET_ERROR){printf("接收出错%d\n",WSAGetLastError());int rua;scanf("%d", &rua);return;}else if(irecv==0)break;else{printf("\n%s--",recv_buf);printf("Server received from Client ip:[%s],port:[%d]\n",inet_ntoa(cliadd.sin_addr),ntohs(cliadd.sin_port));}scanf("%s",send_buf);sendto(sSocket,send_buf,sizeof(send_buf),0,(structsockaddr*)&cliadd,sizeof(cliadd));}closesocket(sSocket);WSACleanup();}客户端:#include "stdafx.h"#include<winsock2.h>#include <stdio.h>#define data_buffer 1024void main(){WSADATA wsadata;SOCKET sclient;//服务器地址、端口号char * serip="192.168.8.58";int Seriport=6666;char ch[]="qita";//服务器SOCKET地址结构长度int ilen;//发送/接收数据大小int isend;int irecv;//要发送给服务器的数据char send_buf[]="hello,I am a client.";char recv_buf[data_buffer];//服务器端的SOCKET地址结构struct sockaddr_in seradd, cliadd;//初始化接收缓冲区memset(recv_buf,0,sizeof(recv_buf));//字符数组初始化memset(ch,0,sizeof(ch));if(WSAStartup(MAKEWORD(2,2),&wsadata)!=0){printf("failed to load winsock\n");return;}// 服务器SOCKET地址结构初始化seradd.sin_family=AF_INET;seradd.sin_port=htons(Seriport);seradd.sin_addr.s_addr=inet_addr(serip);cliadd.sin_family=AF_INET;cliadd.sin_port=htons(7777);cliadd.sin_addr.s_addr=inet_addr("0.0.0.0");sclient=socket(AF_INET,SOCK_DGRAM,0);if(sclient==INVALID_SOCKET){printf("build socket failed!\n");return;}if(bind(sclient,(LPSOCKADDR)&cliadd,sizeof(cliadd))==SOCKET_ERROR ){printf("地址绑定时出错:%d\n",WSAGetLastError());return;}//无连接不需要进行地址与套接字的绑定,直接发送数据即可ilen=sizeof(seradd);isend=sendto(sclient,send_buf,sizeof(send_buf),0,(struct sockaddr *)&seradd,ilen);if(isend!=0&&isend!=SOCKET_ERROR){//printf("data has been sent successfully!\n");printf("客户所发的数据为:%s, 字节数为:%d\n",send_buf,isend);}else return;while(1){scanf("%s",ch);sendto(sclient,ch,sizeof(ch),0,(structsockaddr*)&seradd,sizeof(seradd));irecv=recvfrom(sclient,recv_buf,data_buffer,0,(structsockaddr*)&seradd,&ilen);if(irecv==SOCKET_ERROR){printf("接收出错%d\n",WSAGetLastError());int rua;scanf("%d", &rua);return;}else if(irecv==0)break;else{printf("\n%s--",recv_buf);printf("Server received from Client ip:[%s],port:[%d]\n",inet_ntoa(seradd.sin_addr),ntohs(seradd.sin_port));}}closesocket(sclient);WSACleanup();}本机上客户端与服务器端通信结果如图:在两台服务器上分别运行服务器端和客户端,结果如图:三、实验中出现的问题实验中,因为对TCP和UDP中的代码不熟悉,编译时也缺少了头文件,导致在编译时一直都没有通过,最后在老师的提醒下知道了错误所在,才能编译通过。