本来想写个聊天系统,暂时水平有限,不浪费时间,以后再补上吧
本机ip地址: 127.0.0.1 代表的就是本机的ip地址,也可以用局域网ip 192....
端口号:TCP/IP协议中的端口,端口号的范围从 0 ~ 65535, 比如HTTP服务80端口, FTP服务21端口
1 知名端口
众所周知的端口号,范围0~1023,这些分配给系统用,或一些知名的服务来用的。
2 动态端口
这些端口号一般不固定分配给某个服务,也就是说许多服务都可以使用这些端口。范围 1024 ~ 65535
比如1024端口就是分配给第一个向系统发出网络申请的程序。关闭程序进程后,就会释放所占用的端口。如果端口已被占用,第二个程序是连接不上服务器的。
网络通信是如何确定主机和要交换的程序的?
1,网间进程通信要解决的是不同主机进程间的相互通信问题
2, 操作系统支持的网络协议众多,不同协议的工作方式不同,地址格式也不同。进程通信还要解决多重协议的识别问题。
TCP/IP 协议族已经帮我们解决了这个问题。网络层的“IP地址”可以唯一标识网络中的主机, 而传输层的 “协议+端口“可以唯一识别主机的应用程序(进程)。
这样利用三元组 (ip地址, 协议, 端口) 就可以标识网络的进程了。
服务器代码:
#include <Winsock2.h>
#include <stdio.h>
#include <iostream>
#pragma comment (lib, "ws2_32.lib")
using namespace std;
void main()
{
//windows特有 使用WSAStarup() 初始化套接字库。相当于分配网络资源
WSADATA wsaData;
int err = WSAStartup(0x0101, &wsaData);
if (err != 0 )
{
return;
}
//windows特有 设置网络库的版本
if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
{
//windows 特有 对应的网络资源释放
WSACleanup();
return;
}
//创建套接字 AF_INET 代表IPV4 SOCK_STREAM socket类型 0指定协议类型 0默认IPPROTO_TCP tcp协议
SOCKET sockServ = socket(AF_INET, SOCK_STREAM, 0);
if (INVALID_SOCKET == sockServ)
{
WSACleanup(); //这时候只是设置 socket参数 并没有创建 所以不需要closeSocket(sock_id);
return;
}
// 上面同linux socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1
SOCKADDR_IN addrServ;
//ip地址设置为 INADDR_ANY,让系统自动获取本机地址
addrServ.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //htonl 转换ip地址格式的函数
addrServ.sin_port = htons(6000);//设置端口号6000
addrServ.sin_family = AF_INET; //IPV4
//把地址组中特定的地址 赋值给socket
err = bind(sockServ, (SOCKADDR*)&addrServ, sizeof(SOCKADDR));
if (0 != err)
{
WSACleanup();//这时候也没有真正的创建socket 也是再设置必要的参数
return;
}
//这时候真正创建了socket 监听该socket 设置最大连接数量
listen(sockServ, SOMAXCONN);
//循环监听客户端请求 这里将会存储每个客户端的信息 比如ip 端口
SOCKADDR_IN addrClient;
int len = sizeof(SOCKADDR);
while(1)
{
//接受客户端请求 客户端信息放在addrClient 如果不关心 后面连个参数都可以设为NULL
//阻塞直到有客户端连接,不然多浪费CPU资源。
SOCKET sockConn = accept(sockServ, (SOCKADDR*)&addrClient, &len);
char sendBuf[255];
cin >> sendBuf ;
//send 向客户端发送数据
send(sockConn, sendBuf, strlen(sendBuf) + 1, 0);
char recvBuf[255];
//接受客户端传来的数据 接受的数据写入到recvBuf
int nRecv = recv(sockConn, recvBuf, 255, 0);
if (nRecv > 0)
{
recvBuf[nRecv] = '\0';
printf("%s\n", recvBuf);
}
if (strcmp(recvBuf, "88") == 0)
closesocket(sockConn);
}
closesocket(sockServ);
}
客户端代码:
#include <Winsock2.h>
#include <stdio.h>
#include <iostream>
#pragma comment (lib, "ws2_32.lib")
using namespace std;
void main()
{
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(1, 1); //设置请求套接字1.1版本
int err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
return;
//检查是否是1.1版本 不是返回
if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
{
WSACleanup();
return;
}
//创建socket IPV4 socket type SOCK_STREAM 0代表默认TCP协议
SOCKET sockConn = socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN addrServ;
addrServ.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//设置连接的地址
addrServ.sin_family = AF_INET; //IPV4
addrServ.sin_port = htons(6000); //设置连接的端口号
while(1)
{
//连接设置的服务器
connect(sockConn, (SOCKADDR *)&addrServ, sizeof(SOCKADDR));
char recvBuf[255] ="\0";
//接受服务器发来的数据
recv(sockConn, recvBuf, 255, 0);
if (strcmp(recvBuf, "") != 0 )
cout << recvBuf << endl;
char sendBuf[255];
cin >> sendBuf ;
//向服务器发送数据
send(sockConn, sendBuf, strlen(sendBuf), 0);
sendBuf[strlen(sendBuf)] = '\0';
if (strcmp(sendBuf, "88") == 0 )
break;
}
//关闭socket
closesocket(sockConn);
//释放分配的网络资源
WSACleanup();
}
对比linux socket http://blog.csdn.net/tutuboke/article/details/45840367