服务端的建立:
1, 加载SOCKET版本
2, 创建socket
3, 创建SOCKADDR_IN结构变量, 设置IP, 端口, 与地址族
4, 绑定IP与端口
5, 打开监听
6, 接收客户端连接请求
7, 开启通信.
客户端的建立:
1, 加载SOCKET版本
2, 创建socket
3, 创建SOCKADDR_IN结构变量, 设置IP, 端口, 与地址族
4, 连接服务端
5, 开启通信
windows下服务端的例子:
#include "stdafx.h"
#include <WinSock2.h>
int _tmain(int argc, _TCHAR* argv[])
{
using std::cout;
WORD wVersion;
WSADATA wsaData;
wVersion = MAKEWORD(2, 2); //设置版本
//WSAStartup 加载SOCKET版本, 成功返回0, 否则返回-1
if (WSAStartup(wVersion/*设定的版本号*/,
&wsaData/*OUT参数, 获取加载的版本信息*/))
{
cout<<"加载SOCK出错";
std::cin.get();
return -1;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) !=2)
{//验证版本信息是不为2, 2
cout<<"加载SOCK版本出错";
std::cin.get();
//WSACleanup释放资源, 终止对SOCKET动态库的使用
WSACleanup();
return -1;
}
int sockLength = sizeof(SOCKADDR);
//socket创建SOCKET, 成功返回一个新的SOCKET数据类型的套接字描述符, 失败返回 INVALID_SOCKET
SOCKET sockServer = socket(AF_INET/*地址族*/,
SOCK_STREAM/*指定流式套接字*/,
0/*一般设置为0, 自动选择一个合适的协议*/);
SOCKADDR_IN sAddress;
//inet_addr(将字符串IP型式转换为指定的ulong类型地址描述)
//inet_ntoa(将指定的ulong类型地址描述转换成字符串IP型式)
sAddress.sin_addr.S_un.S_addr = inet_addr("192.168.1.100");
sAddress.sin_family = AF_INET;
//htons把一个u_short类型的值从主机字节顺序转换为TCP/IP网络字节顺序
//htonl把一个u_long类型的值从主机字节顺序转换为TCP/IP网络字节顺序
sAddress.sin_port = htons(7777);
//bind, 将该套接字绑定到指地的IP和端口上, 成功返回0, 否则返回 SOCKET_ERROR
bind(sockServer, //创建的SOCKET
(SOCKADDR*)&sAddress, //地址信息
sockLength/*SOCKADDR的字节长度sizeof(SOCKADDR)*/);
//listen, 开启监听, 成功返回0, 否则返回SOCKET_ERROR
listen(sockServer,//创建的SOCKET
10/*打开服务会监听的客户数量*/);
SOCKADDR_IN clientAddress;
while(TRUE)
{
//accept接收客户端发送的连接请求, 成功, 返回该客户端的SOCKET, 否则返回-1
SOCKET client = accept(sockServer, //服务端SOCKET
(SOCKADDR*)&clientAddress, //用来接收客户端地址
&sockLength/*sizeof(SOCKADDR)*/);
cout<<"链接OK";
char sendBuffer[512];
sprintf(sendBuffer, "%s 以登录成功",
inet_ntoa(clientAddress.sin_addr)/*将ulong型式地址转换成字符串型式的IP地址*/);
//send发送消息
send(client, sendBuffer, strlen(sendBuffer) + 1/*这里注要多加1用来存放\0*/, 0);
char recvBuffer[512] = {0};
//recv接收消息, 失败返回0或者-1
recv(client, recvBuffer, 512, 0);
cout<<recvBuffer;
closesocket(client);
}
cout<<"成功";
std::cin.get();
WSACleanup();
return 0;
}
windows下客户端的例子:
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
WORD wVersion;
WSADATA wsaData;
wVersion = MAKEWORD(2, 2);
if (WSAStartup(wVersion, &wsaData))
{
std::cout<<"加载SOCK出错";
std::cin.get();
return -1;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
std::cout<<"加载SOCK版本出错";
std::cin.get();
WSACleanup();
return -1;
}
SOCKET client = socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN hostAddress;
hostAddress.sin_addr.S_un.S_addr = inet_addr("192.168.1.100");
hostAddress.sin_family = AF_INET;
hostAddress.sin_port = htons(7777);
//connect连接指定的地址与端口
int i = connect(client, (SOCKADDR*)&hostAddress, sizeof(SOCKADDR));
if (i == 0)
{
std::cout<<"连接成功\n";
}
char recvBuffer[512];
recv(client, recvBuffer, 512, 0);
std::cout<<recvBuffer;
char sendBuffer[511];
sprintf(sendBuffer, "客户端 登录成功");
send(client, sendBuffer, strlen(sendBuffer) + 1/*这个很关键*/, 0);
closesocket(client);
WSACleanup();
std::cin.get();
return 0;
}
这里仅是未了说明套接字的使用, 在实际应用当中, 都必需结合多线程处理套接字, 最好还要封装之后再使用
windows下获取本机IP:
char * IegadSock::GetHostIp()
{//获取本机IP
WSADATA wData;
unsigned int version = MAKEWORD(2, 2);
if (WSAStartup(version, &wData))
{
return 0;
}
if (LOBYTE(wData.wVersion) != 2 || HIBYTE(wData.wVersion) != 2)
{
return 0;
}
char host_name[255]; //计算机名
if (gethostname(host_name/*输出参数*/, sizeof(host_name)) == -1) //该函数获取计算机名
{//该函数, 成功返回0
return 0;
}
//gethostbyname()返回对应于给定主机名的包含主机名字和地址信息的hostent结构指针,失败返回NULL
HOSTENT * phe = gethostbyname(host_name/*计算机名*/);
if (!phe)
{
return 0;
}
in_addr addr;
//获取HOSTENT中的地址列表中第一个地址,并转换成字符串
memcpy(&addr, phe->h_addr_list[0], sizeof(in_addr));
char * IpString = inet_ntoa(addr);
WSACleanup();
return IpString;
}
这里是Linux下的服务端:
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <iostream>
int main()
{
//unlink("server_socket");
int host = socket(AF_INET, SOCK_STREAM, 0);
if(host == -1)
{
std::cout<<"init error\n";
return -1;
}
std::cout<<"init done\n";
sockaddr_in s_add;
s_add.sin_family = AF_INET;
s_add.sin_addr.s_addr= inet_addr("192.168.1.104");
s_add.sin_port=htons(7777);
int err = bind(host, (sockaddr*)&s_add, sizeof(sockaddr));
if (err == -1)
{
std::cout<<"bind error\n";
}
std::cout<<"bind done\n";
err = listen(host, 10);
if (err == -1)
{
std::cout<<"listen error\n";
}
std::cout<<"listen...\n";
sockaddr_in c_add;
int len = sizeof(c_add);
int clnt = accept(host, (sockaddr*)&c_add, (socklen_t*)&len/*这里和windows下有区别*/);
if(clnt == -1)
{
std::cout<<"accpet error\n";
}
std::string sendMsg = "Hello guy\n";
err = write(clnt, sendMsg.c_str(), sendMsg.size() + 1);
if(err == -1)
{
std::cout<<"write error\n";
}
char msg[1024] = {0};
read(clnt, msg, 1024);
std::cout<<msg<<std::endl;
close(clnt);
close(host);
return 0;
}
在linux下,是不需要加载版本的.也就是(WSAStartup()的调用)