//简单的socket通信,太久不写总会忘记基本的框架,以便以后看看
//1.记的最初学socket通信,总是很纠结客户端连接服务端成功后,是先发送还是接收了?
// 那时候想多了,多写写就行。可以向http那样,客户端先连接然后发送GET/POST,服务端收到客户端请求后,
// 发送请求内容到客户端。客户端接收请求关闭。可以研究下tinyhttpd
//2.写了些简单的socket通信后,然后不知道干嘛了?
// 可以学着写select,epoll。这样能明白很多。
//3.真正工作设需要的就是模式,和ioctlsocket()或fcntl()设置,这些真需要在项目中实际,看半天看懂其实没那么懂
//服务端
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
#ifdef WINDOWS_SOCK
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
#define socklen_t int
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#define SOCKET int
#define SOCKET_ERROR -1
#define INVALID_SOCKET ~0
#endif
#define PORT 8080
/*
*socket 服务器端
*/
int main()
{
#ifdef WINDOWS_SOCK
//1.winows sock init
WORD word = MAKEWORD(2,2);
WSADATA wsaData;
//异步sock初始化,0成功
int err = WSAStartup(word, &wsaData);
if(err!=0)
{
printf("Failed to load Winsock./n");
return -1;
}
#endif
//2.sock
//AF_INET为ipv4地址32位与端口16位。SOCK_STREAM为TCP连接。IPPROTO_TCP为TCP传输协议
SOCKET sockListen = socket(AF_INET,SOCK_STREAM, 0);//创建服务器端套接口
if(sockListen == INVALID_SOCKET)
{
printf("socket() Failed");
return -1;
}
#ifdef WINDOWS_SOCK
//iMode为0则阻塞,非0不阻塞
u_long iMode = 0;
if(ioctlsocket(sockListen, FIONBIO, &iMode) != NO_ERROR)
{
printf("ioctlsocket error");
}
#else
int flags = fcntl(sockListen, F_GETFL, 0);
//0为阻塞,flags | O_NONBLOCK为非阻塞
//if (fcntl(sockListen, F_SETFL, flags | O_NONBLOCK) < 0)
if (fcntl(sockListen, F_SETFL, 0) < 0)
{
printf("fcntl error!");
}
#endif
//3.bind
sockaddr_in addr;//服务器和客户的地址
memset(&addr, 0, sizeof(addr));
//使用IP地址族
addr.sin_family = AF_INET;
//使用htons()把双字节主机序端口号转换为网络字节序端口号
addr.sin_port = htons(PORT);
//htonl()把一个四字节主机序IP地址转换为网络字节序主机地址
//使用系统指定的IP地址INADDR_ANY
addr.sin_addr.s_addr = htonl(INADDR_ANY);
//bind()函数进行套接定与地址的绑定,成功为0
if(bind(sockListen,(sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)
{
printf("bind() Failed /n");
return -1;
}
//4.listen
//进入监听状态,监听数量5,正确返回0
if(listen(sockListen, 5) == SOCKET_ERROR)
{
printf("lisiten() Failed/n");
return -1;
}
//5.accept
//初始化客户地址长度参数
//进入一个无限循环,等待客户的连接请求
SOCKET sockAccept;
while(1)
{
sockaddr_in addrClient;//服务器和客户的地址
socklen_t iLen = sizeof(sockaddr_in);
sockAccept = accept(sockListen, (struct sockaddr *)&addrClient, &iLen);
if(sockAccept == INVALID_SOCKET)
{
printf("accept() Failed: /n");
continue;
}
//输出客户IP地址和端口号
printf("Accepted client IP:[%s],port:[%d]/n",inet_ntoa(addrClient.sin_addr),ntohs(addrClient.sin_port));
//给连接的客户发送信息
//6.send
char buf[1024] = "I am a server";//要发送给客户的信息
int iSend;
ifstream ifs("msg.txt", ifstream::in);
if(ifs.is_open())
{
string s;
while (getline(ifs, s))
{
iSend = send(sockAccept, s.c_str(), s.size(),0);
if(iSend == SOCKET_ERROR)
{
cout<<"send error"<<endl;
}
else if(iSend == 0)
{
cout<<"isend == 0"<<endl;
continue;
}
else
{
cout<<s<<"size:"<<strlen(buf)<<endl;
}
}
}
#ifdef WINDOWS_SOCK
closesocket(sockAccept);
#else
close(sockAccept);
#endif
}
#ifdef WINDOWS_SOCK
closesocket(sockListen);
WSACleanup();
#else
close(sockListen);
#endif
return 0;
}
//客户端
#include <iostream>
#include <string>
#ifdef WINDOWS_SOCK
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
#define socklen_t int
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define SOCKET int
#define SOCKET_ERROR -1
#define INVALID_SOCKET ~0
#endif
using namespace std;
#define PORT 8080
#define DATA_BUFFER 1024
/*
*客户端
*/
int main()
{
int iLen;//从服务器端接收的数据长度
struct sockaddr_in addr;//服务器端地址
char buf[DATA_BUFFER];//接收数据的缓冲区
memset(buf,0,sizeof(buf));//接收缓冲区初始化
#ifdef WINDOWS_SOCK
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
{
printf("Failed to load Winsock./n");
return -1;
}
#endif
//1.socket
//建立客户端流式套接口
SOCKET sockClient = socket(AF_INET,SOCK_STREAM, 0);
if(sockClient == INVALID_SOCKET)
{
printf("socket() Failed /n");
return -1;
}
//2.connect请求与服务器端建立TCP连接
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
//inet_addr()将命令行中输入的点分IP地址转换为二进制表示的网络字节序IP地址
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
if(connect(sockClient,(struct sockaddr *)&addr, sizeof(addr)) == INVALID_SOCKET)
{
printf("connect() Failed \n");
}
else
{
//send
string s = "hello, come from client!";
int slen = strlen(s.c_str());
{
iLen = send(sockClient, s.c_str(), slen, 0);
if (iLen == 0)
{
cout<<"send 0"<<endl;
}
else if (iLen < 0)
{
cout<<"send -1"<<endl;
}
else
{
cout<<"send: "<<iLen<<endl;
}
}
//recv
while(true)
{
iLen = recv(sockClient,buf,sizeof(buf),0);
if(iLen == 0)
{
cout<<"iLen = 0"<<endl;
break;
//continue;
}
else if ( iLen == SOCKET_ERROR)
{
cout<<"recv() failed"<<endl;
return -1;
}
else
{
buf[iLen] = '\0';
cout<<"length:"<<iLen<<" buf:"<<buf<<endl;
}
}
}
#ifdef WINDOWS_SOCK
closesocket(sockClient);
cout<<"sock close"<<endl;
WSACleanup();
#else
close(sockClient);
#endif
system("pause");
return 0;
}