流式套接字实现简单的客户端/服务端通信过程

来源:互联网 发布:天地图数据融合 编辑:程序博客网 时间:2024/06/07 03:46

一、 实验内容

  • 熟悉流式套接字socket函数的使用方法,包括建立连接、数据发送/接收和关闭连接等;
  • 客户端可向服务端发送任意字符串,服务端在接收到该字 符串后,回送给客户端;(此过程可循环)
  • 服务端在接收到新连接后,能够打印出客户端的ip和端口;(如何获取连接套接字上的地址信息,请自行查阅资料)
  • 服务端采用多线程模式,能够同时接收多个客户端的连接请求,为每个客户端连接开启一个线程;(多线程编程自行查阅资料)

二、 实验要求

  提交源码(源码编写要规范)、可执行程序、实验报告(要有程序运行截图)。



基本知识:

SOCKET socket(int af,// 目前只提供PF_INET(AF_INET)int type,// Socket的类型(SOCK_STREAM、SOCK_DGRAM)int protocol,// 通讯协议(如果使用者不指定,则设为0));

bind(    _In_ SOCKET s,// Socket对象名    _In_reads_bytes_(namelen) const struct sockaddr FAR * name,//结构体 Socket的地址值,即所在及其的IP地址    _In_ int namelen    );    //调用bind()函数之后,为socket()函数创建的套接字关联一个相应地址,发送到这个地址
int listen(SOCKET s,// 需要建立监听的Socketint backlog,// 最大连接个数);
accept(    _In_ SOCKET s,    _Out_writes_bytes_opt_(*addrlen) struct sockaddr FAR * addr,    _Inout_opt_ int FAR * addrlen    );
int recv(SOCKET s,// Socket的识别码char FAR *buf,// 存放接收到的数据的缓存区int len,// buf的长度int flags// 此函数被调用的方式);int send(SOCKET s,// Socket的识别码const char FAR *buf,// 存放要传送的数据的缓存区int len, // buf的长度int flags// 此函数被调用的方式);
CreateThread(    _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,    _In_ SIZE_T dwStackSize,    _In_ LPTHREAD_START_ROUTINE lpStartAddress,加载函数地址    _In_opt_ __drv_aliasesMem LPVOID lpParameter,加载函数参数    _In_ DWORD dwCreationFlags,    _Out_opt_ LPDWORD lpThreadId    );




connect(    _In_ SOCKET s,    _In_reads_bytes_(namelen) const struct sockaddr FAR * name,    _In_ int namelen    );
int recv(SOCKET s, // Socket的识别码char FAR *buf, // 存放接收到的数据的缓存区int len, // buf的长度int flags // 此函数被调用的方式);int send(SOCKET s,// Socket的识别码const char FAR *buf,// 存放要传送的数据的缓存区int len, // buf的长度int flags// 此函数被调用的方式);

编译器报错C4996:

(1)使用VS提供的 编译器选择性提供warning功能

使用 #pragma warning( disable :4996) 即可消除。

(2) 设置预处理选项:a. Projectproperties->ConfigurationProperties->C/C++->Preprocessor->Preprocessor Definitionsb.

点击按钮(...)c. 输入:_CRT_SECURE_NO_WARNINGS。

注:使用 "\n" 相隔

(3)在引用库文件开头写一个宏定义

#define _CRT_SECURE_NO_WARNINGS

 #include <stdio.h>






源码

server

#include<iostream>#include<winsock2.h>#pragma comment(lib, "ws2_32.lib")#define IP_ADDRESS "127.0.0.1"#define PORT 4445#pragma warning(disable:4996)using namespace std;DWORD WINAPI ClientThread(LPVOID lpParameter){SOCKET ClientSocket = (SOCKET)lpParameter;sockaddr_in ClientAddr;int Len = sizeof(ClientAddr);char RecvBuffer[MAX_PATH];int Ret = 0;while (true) {memset(RecvBuffer, 0x00,sizeof(RecvBuffer));Ret = recv(ClientSocket, RecvBuffer, MAX_PATH, 0);getpeername(ClientSocket,(struct sockaddr *)&ClientAddr,&Len);if (Ret == SOCKET_ERROR || Ret ==0){cout << "Client "<<inet_ntoa(ClientAddr.sin_addr) <<":"<<ClientAddr.sin_port<<" Exit!"<<endl;break;}cout << "Client " << inet_ntoa(ClientAddr.sin_addr) << ":" << ClientAddr.sin_port << "   connect" << endl;cout << "receive" << " message:" << RecvBuffer<<endl;send(ClientSocket, RecvBuffer, MAX_PATH, 0);}return 0;}int main(int argc, char * argv[]){WSADATA Ws;SOCKET ClientSocket,ServerSocket;struct sockaddr_in ClientAddr,ServerAddr;int Ret = 0;int Len = 0;HANDLE hThread = NULL;if (WSAStartup(MAKEWORD(2, 2), &Ws) != 0){cout << "Windows Init Error " << GetLastError() << endl;return - 1;}ServerAddr.sin_family = AF_INET;ServerAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);ServerAddr.sin_port = htons(PORT);memset(ServerAddr.sin_zero,0x00,8);//create socketServerSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if (ServerSocket == INVALID_SOCKET){cout << "create socket Error::" << endl;return -1;}//bindRet = bind(ServerSocket,(struct sockaddr *)&ServerAddr,sizeof(ServerAddr));if (Ret != 0){cout << "bind Error::" << GetLastError() << endl;return -1;}Ret = listen(ServerSocket, 5);if (Ret != 0){cout << "listen Error::" << GetLastError() << endl;return -1;}cout << "server is up" << endl;//接受数据while (true){Len = sizeof(ClientSocket);ClientSocket = accept(ServerSocket,(struct sockaddr *)&ClientAddr,&Len);if(ClientSocket == INVALID_SOCKET){cout << "accept Error" << GetLastError() << endl;return -1;}hThread = CreateThread(NULL, 0, ClientThread, (LPVOID)ClientSocket, 0, NULL);if (hThread == NULL){cout << "create hthread Error::" << endl;break;}CloseHandle(hThread);}closesocket(ClientSocket);closesocket(ServerSocket);WSACleanup();return 0;}

Client:

#include<iostream>#include<winsock2.h>#pragma comment(lib,"ws2_32.lib")#define IP_ADDRESS "127.0.0.1"#define PORT 4445#pragma warning(disable:4996)using namespace std;int main(int argc, char *argv[]){WSADATA Ws;SOCKET ClientSocket;int Ret = 0;char SendBuffer[MAX_PATH];char RecvBuffer[MAX_PATH];if (WSAStartup(MAKEWORD(2, 2), &Ws) != 0){cout << "Windows Init Error::" << GetLastError() << endl;return -1;}//create socketClientSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if (ClientSocket == INVALID_SOCKET){cout << "create Socket Error::" << endl;return -1;}sockaddr_in ClientAddr;ClientAddr.sin_family = AF_INET;ClientAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);ClientAddr.sin_port = htons(PORT);memset(ClientAddr.sin_zero,0x00,8);Ret = connect(ClientSocket, (struct sockaddr *)&ClientAddr, sizeof(ClientAddr));//==SOCKET_ERRORif (Ret == SOCKET_ERROR){cout << "connect Error::" << GetLastError() << endl;return -1;}cout << "Connect Success!"<<endl;//send while (true){cin.getline(SendBuffer,sizeof(SendBuffer));Ret = send(ClientSocket,SendBuffer,(int)sizeof(SendBuffer),0);if (Ret == SOCKET_ERROR){cout << "send Error::" <<GetLastError()<< endl;break;}memset(RecvBuffer, 0x00, sizeof(RecvBuffer));Ret = recv(ClientSocket, RecvBuffer, MAX_PATH, 0);cout << "message::" << SendBuffer << endl;cout << "receive message::" << RecvBuffer << endl;}closesocket(ClientSocket);WSACleanup();return 0;}


阅读全文
0 0
原创粉丝点击