一 注意问题:
1: recv函数
int recv( _In_ SOCKET s, _Out_ char *buf, _In_ int len, _In_ int flags);
第三个参数指明buf的长度; len = sizeof(buf), 而不用 len=strlen(buf) 。
2: 服务器端的send函数的第一个参数用accept返回的SOCKET, 客户端的用SOCKET函数返回值
二 代码
1 . mysocket.h
const size_t IP_BUF_SIZE = 65;
class MySocket{
public:
SOCKET m_socket;
SOCKET m_con;
public:
void init();
void mybind();
void mylisten();
SOCKET myaccept();
void mysend(SOCKET socket);
void myrecv(SOCKET socket);
void myclose();
void myconnect();
};
2 mysocket.cpp
#include <Winsock2.h>
#include <ws2tcpip.h>
#include <iostream>
#include "mysocket.h"
#pragma comment(lib, "ws2_32.lib") //socket编程需要引用该库
void MySocket::init(){
WSADATA wsa_data; //WSADATA变量,包含windows socket执行的信息
int sys_fun_result = 0;
// 初始化winsock动态库(ws2_32.dll),MAKEWORD(2, 2)用于请求使用winsock2.2版本
sys_fun_result = WSAStartup(MAKEWORD(2, 2), &wsa_data);
if (sys_fun_result != 0) {
std::cout << "WSAStartup() function failed: " << sys_fun_result << "\n";
system("pause");
return ;
}
m_socket=socket(PF_INET,SOCK_STREAM,0);//创建套接字
std::cout<<"Winsock初始化成功"<<std::endl;
}
void MySocket::mybind(){
int sys_fun_result = 0;
SOCKADDR_IN addr;
addr.sin_family=AF_INET;
//addr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//ip地址
addr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
addr.sin_port=htons(16001);//绑定端口
bind(m_socket,(SOCKADDR*)&addr,sizeof(SOCKADDR));//绑定
if (sys_fun_result == SOCKET_ERROR) {
std::cout << "bind() function failed with error: " << WSAGetLastError() << "\n";
closesocket(m_socket);
WSACleanup();
return ;
}
}
void MySocket::mylisten(){
int sys_fun_result = 0;
sys_fun_result = listen(m_socket, SOMAXCONN);// SOMAXCONN 默认值 5 代表能够接收的最多的连接
if (sys_fun_result == SOCKET_ERROR) {
std::cout << "listen() function failed with error: " << WSAGetLastError() << "\n";
closesocket(m_socket);
return ;
}
}
SOCKET MySocket::myaccept(){
char ip_buf[IP_BUF_SIZE];
SecureZeroMemory(ip_buf, IP_BUF_SIZE);
SOCKADDR_IN clientsocket;
int len=sizeof(SOCKADDR);
m_con=accept(m_socket,(SOCKADDR*)&clientsocket,&len);
if (m_con == INVALID_SOCKET) {
std::cout << "accept() function failed with error: " << WSAGetLastError() << "\n";
closesocket(m_socket);
WSACleanup();
system("pause");
return NULL;
}
//ip地址转换
inet_ntop(AF_INET, &clientsocket, ip_buf, IP_BUF_SIZE);
std::cout << "client ip address: " << ip_buf << std::endl;
return m_con;
}
void MySocket::mysend(SOCKET socket){
int sys_fun_result = 0;
char sendBuf[100]="xw" ;
//memset(sendBuf,0,sizeof(sendBuf));
;
sys_fun_result= send(socket,sendBuf,5,0);
if(sys_fun_result==SOCKET_ERROR){
std::cout << "mysend() function failed with error: " << WSAGetLastError() << "\n";
}
std::cout<<sys_fun_result<<std::endl;
std::cout<<strlen(sendBuf)<<std::endl;
std::cout<<sizeof(sendBuf)<<std::endl;
std::cout<<sendBuf;
}
void MySocket::myrecv(SOCKET socket){
char receiveBuf[100];
int sys_fun_result = 0;
memset(receiveBuf,0,sizeof(receiveBuf));
/* 当recv返回值小于0时,socket报错;
当recv返回值大于0时,成功,返回值为接收到的数据长度;
当recv返回值等于0时,表示此时connect已经关闭,没有接收到数据。*/
sys_fun_result=recv(socket,receiveBuf,sizeof(receiveBuf),0);//这里不能用 strlen(receiveBuf) 因为 strlen(receiveBuf)=0
if (sys_fun_result == SOCKET_ERROR)
{
std::cout<<"error with code = "<<WSAGetLastError()<<std::endl;
exit(1);
}
printf("receiveBuf=%s\n",receiveBuf);
std::cout<<receiveBuf;
}
void MySocket::myclose(){
closesocket(m_con);//关闭
WSACleanup();//释放资源的操作
}
void MySocket::myconnect(){
int sys_fun_result = 0;
SOCKADDR_IN clientsock_in;
clientsock_in.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
clientsock_in.sin_family=AF_INET;
clientsock_in.sin_port=htons(16001);
sys_fun_result = connect(m_socket,(SOCKADDR*)&clientsock_in,sizeof(SOCKADDR));
if (sys_fun_result == SOCKET_ERROR) {
std::cout << "connect() function failed with error: " << WSAGetLastError() << "\n";
WSACleanup();
system("pause");
return ;
}
}
3 client.cpp
#include <windows.h>
#include "mysocket.h"
void main1(){
MySocket * mysocket= new MySocket();
mysocket->init();
mysocket->myconnect();
mysocket->mysend(mysocket->m_socket);
system("pause");
}
4 server.cpp
#include <windows.h>
#include "mysocket.h"
void main(){
MySocket * mysocket= new MySocket();
mysocket->init();
mysocket->mybind();
mysocket->mylisten();
SOCKET socket=mysocket->myaccept();
mysocket->myrecv(socket);
mysocket->myclose();
system("pause");
}
三 :遗留问题
1 客户端调用两次send函数,服务器只会接受一次,服务器就会断开本次连接。