-
ip地址: ( ipv4)
- 功能:唯一标识网络上的主机
- 数据:无符号4字节整型uint32_ _t源ip地址->目的ip地址数量: 43亿--不够用
- 谁上网给谁分配---dhcp,ip地址替换---NAT,ipv6--ip地址16个字节ipv6并不兼容ipv4套接字编程
- 两台主机之间进行网络通信--必定有一方是主动方客户端(主动方) ---请求--->服务器(被动方)
- tcp(传输控制协议)---有连接,可靠传输,面向字节流
- 确保数据能够到达对端--确保数据的安全传输,传输灵活--传输速率低,粘包问题udp(用户数据报协议)---无连接,不可靠,面向数据报
- 无法保证数据的安全传输,传输不太灵活--传输速度快,无粘包问题
- 对数据安全性要求高的程序用tcp--文件传输
- 对数据的实时性要求高的程序用udp--传视频
-
port端口:
- 功能:用于唯一标识主机上处理数据的进程
- 数据:无符号2个字节的整数unit16_ t 65535
- 源ip,源端口,目的ip,目的端口,协议->(sip, sport, dip, dport, proto)五元组--标识- - -条通信
-
网络字节序:
- 字节序: cpu对数据进行存取的顺序--存取大小大于1个字节的数据
- 大端字节序:小端字节序
- 通信双方无法确定双方的电脑字节序的时候,发送一个大于一个字节存储的数据就有可能造成数据错误
- 解决方法:网络通信统一采取大端字节序
-
socket接口:
-
UdpServer.cc:
#include <iostream>
#include <stdlib.h>
#include <string>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <unistd.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <errno.h>
#include <strings.h>
using namespace std;
//定义一个服务
class UdpServer
{
private:
int sock;//文件描述符
string ip;//ip地址
uint16_t port;//端口号
public:
UdpServer(string ip_, uint16_t port_):ip(ip_),port(port_)
{
}
//创建套接字
void InitSever()
{
sock = socket(AF_INET, SOCK_DGRAM, 0);
cout << sock << endl;
if(sock < 0)
{
cerr << "socket error!" << endl;
exit(2);
}
//绑定信息
struct sockaddr_in local;
local.sin_family = AF_INET;
local.sin_port = htons(port);//端口号转换
local.sin_addr.s_addr = inet_addr(ip.c_str());
if(bind(sock, (struct sockaddr*)&local,sizeof(local)) < 0)
{
cerr << "bind error!" << endl;
exit(3);
}
}
//收数据
void RecvData(string& out, struct sockaddr_in &peer,socklen_t &len)
{
char buf[1024];
ssize_t s = recvfrom(sock, buf, sizeof(buf)-1, 0, (struct sockaddr*)&peer, &len);
//收数据的信息,放在哪儿,期望放多少,还有收数据的对方的信息
if(s > 0)
{
buf[s] = 0;
out = buf;
}
else
{
cerr << "recvfrom error!" << endl;
}
}
//发数据
void SendData(string &in, struct sockaddr_in &peer, socklen_t len)
{
int t = sendto(sock, in.c_str(), in.size(), 0, (struct sockaddr*)&peer, len);//信息从上面的收数据得来
if(t<0)
{
cout << strerror(errno) << endl;
cout << t <<endl;
exit(6);
}
}
void Start()
{
//不断的读写数据
string str;
struct sockaddr_in peer;
//bzero(&peer, sizeof(peer));
socklen_t len = 0;
string suffix = " + UdpServer";
len = sizeof(peer);
while(1)
{
cout<<"222"<<endl;
RecvData(str, peer, len);
cout<<"i333"<<endl;
str += suffix;
cout<<"client# "<<str<<endl;
SendData(str, peer, len);
// int t = sendto(sock, str.c_str(), str.size(), 0, (struct sockaddr*)&peer, len);//信息从上面的收数据得来
cout<<"444"<<endl;
}
}
~UdpServer()
{
close(sock);
}
};
void Usage(string proc)
{
cout << "Usage:" << proc << "ip port" << endl;
}
int main(int argc, char *argv[])
{
if(argc != 3)
{
Usage(argv[0]);
exit(1);
}
string ip = argv[1];
uint16_t port = atoi(argv[2]);
UdpServer server(ip, port);
server.InitSever();
server.Start();
return 0;
}
-
UdpClient.cc:
#include <iostream>
#include <stdlib.h>
#include <string>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <unistd.h>
#include <sys/types.h>
#include <arpa/inet.h>
using namespace std;
//定义一个服务
class UdpClient
{
private:
int sock;//文件描述符 套接字
string server_ip;//ip地址
uint16_t server_port;//端口号
public:
UdpClient(string ip_, uint16_t port_):server_ip(ip_),server_port(port_)
{
}
//创建套接字
void InitSever()
{
sock = socket(AF_INET, SOCK_DGRAM, 0);
if(sock < 0)
{
cerr << "socket error!" << endl;
exit(2);
}
//绑定信息
//struct sockaddr_in local;
//local.sin_family = AF_INET;
//local.sin_port = htons(port);//端口号转换
//local.sin_addr.s_addr = inet_addr(ip.c_str());
//
//if(bind(sock, (struct sockaddr*)&local,sizeof(local)) < 0)
//{
// cerr << "bind error!" << endl;
// exit(3);
//}
}
//收数据
void RecvData(string& out)
{
cout<<"555"<<endl;
struct sockaddr_in peer;
socklen_t len = sizeof(peer);
char buf[1024];
cout<<"7777"<<endl;
ssize_t s = recvfrom(sock, buf, sizeof(buf)-1, 0, (struct sockaddr*)&peer, &len);
cout<<"666"<<endl;
//收数据的信息,放在哪儿,期望放多少,还有收数据的对方的信息
if(s > 0)
{
buf[s] = 0;
out = buf;
}
else
{
cerr << "recvfrom error!" << endl;
}
}
//发数据,要知道发给谁
void SendData(string &in)
{
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(server_port);//端口号转换
server.sin_addr.s_addr = inet_addr(server_ip.c_str());
int ret=sendto(sock, in.c_str(), in.size(), 0, (struct sockaddr*)&server, sizeof(server));//信息从上面的收数据得来
if(ret<0)
{
cerr<<"sendto error"<<endl;
exit(4);
}
}
void Start()
{
//不断的读写数据
string str;
string out;
while(1)
{
cout << "Please Enter# ";
cin >> str;
SendData(str);
cout<<"111"<<endl;
RecvData(out);
cout << "server echo# " << out << endl;
}
}
~UdpClient()
{
close(sock);
}
};
void Usage(string proc)
{
cout << "Usage:" << proc << "server_ip server_port" << endl;
}
// ./client server_ip server_port
int main(int argc, char *argv[])
{
if(argc != 3)
{
Usage(argv[0]);
exit(1);
}
string ip = argv[1];
uint16_t port = atoi(argv[2]);
UdpClient client(ip, port);
client.InitSever();
client.Start();
return 0;
}
-
Makefile:
.PHONY:all
all:client server
client:client.cc
g++ -o $@ $^
server:server.cc
g++ -o $@ $^
.PHONY:clean
clean:
rm -f client server