我们在编写应用程序的时候,必然涉及网络编程,网络编程涉及TCP,UDP,其中TCP又泛生出HTTP编程等,UDP又有单播、广播、组播,这里先讲述TCP编程,其他在后面慢慢讲述。
关于这方面的编程网上的资料真的是太多了。但也不知道是不是大家相互抄袭还是什么,最后编写的的代码基本都是本机对本机通讯的测试代码,根本没有多机之间的通讯,也就是自己的电脑去跟另外一台电脑通讯。我相信每个写出“TCP编程”博客文章的人都掌握了多机通讯,这里为了更好的帮助初学者,在先人基础上,我更加完善一下代码。
TCP肯定有一个服务端和一个客户端,先讲服务端, 流程很简单:
1、初始化(windows平台下必须要这一步,Linux下则没有)
2、socket,创建网络套接字
3、bind,绑定地址跟端口
4、listen,监听
5、accept,接收
6、recv / send (Linux 下为read / write) ,收发数据
掌握这些流程就可以写一个客户端代码了:
我这里是C++编程,但流程是严格按上面6步来的
先建立一个头文件TCPServer.h:
*****************************************分割线**************************************************
#pragma once
#include <stdio.h>
#include <iostream>
using namespace std;
#ifndef WINDOWS //预先定义宏WINDOWS,在Windows vs下项目右键,属性里面添加
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>//close()
#include<netinet/in.h>//struct sockaddr_in
#include<arpa/inet.h>//inet_ntoa
#else
#include <WinSock2.h>
#include <WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
#endif
class TCPServer
{
public:
int init_TCPServer(const char *address, int port); //初始化tcp,socket、bind在这个里面实现
int run(); //listen和accept以及收发数据在这里面
private:
#ifndef WINDOWS
int m_sock; //Linux下套接字类型
#else
SOCKET m_sock; //windows下套接字类型
#endif
};
******************************************类TCPServer中函数的实现(TCPServer.cpp):******************************
#include "TCPServer.h"
int TCPServer::init_TCPServer(const char *address, int port)
{
#ifdef WINDOWS
WSADATA wsaData;
WSAStartup(MAKEWORD(1, 1), &wsaData); //windows下必须要初始化,不然socket会失败
#endif
if ((m_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket failed");
return -1;
}
struct sockaddr_in my_sockaddr;
my_sockaddr.sin_family = AF_INET;
my_sockaddr.sin_port = htons(port); //监听的是本机的端口,不是客户端的端口
if (strcmp(address, "") == 0)
{
my_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); //这是绑定的是自己的IP,跟监听一样,是对本机进行绑定跟监听,不是客户端的,当多机进行通讯时,比如本机是192.168.1.23,客户端是192.168.1.87,这里绑定的是本机的192.168.1.23,而不是客户端的192.168.1.87。但在客户端中,connect中需要给的地址是服务端的,端口也是服务端的
else
{
my_sockaddr.sin_addr.s_addr = inet_addr(address); //跟上面一样
}
if (bind(m_sock, (sockaddr*)&my_sockaddr, sizeof(my_sockaddr)) < 0)
{
perror("bind failed");
return -1;
}
printf("connection...\n");
return 0;
}
int TCPServer::run()
{
if (listen(m_sock, 20) < 0)
{
perror("listen failed");
return -1;
}
struct sockaddr_in my_sockaddr;
#ifndef WINDOWS
int my_recv;
socklen_t len = sizeof(my_sockaddr);
#else
SOCKET my_recv;
int len = sizeof(my_sockaddr);
#endif
while(1)
{
if ((my_recv = accept(m_sock, (sockaddr*)&my_sockaddr, &len)) < 0) //没连接时,函数阻塞
{
perror("accept failed");
return -1;
}
char buf[1024];
memset(buf, 0, sizeof(buf));
#ifndef WINDOWS
int n = read(my_recv, buf, sizeof(buf)); //linux下接受数据函数
#else
int n = recv(my_recv, buf, sizeof(buf), 0); //windows下接受函数
#endif
if (n > 0)
{
printf("recvice from Client: %s\n", buf);
}
}
return 0;
}
*********************************************************************************************
再写一个简单得main.cpp函数
#include "TCPServer.h"
int main()
{
TCPServer myTCPServer;
if (myTCPServer.init_TCPServer("", 8765) == 0)
myTCPServer.run();
return 0;
}
************************************************
服务端就写好了,简单吧,接下来看看服务端的实现,服务端更简单了:
1、初始化 :Windows下必要,Linux下没有
2、socket
3、connect
4、sendto / recv (Linux下为read / write) :收发数据
上代码,先建立头文件,TCPClient.h
*********************************************************
#pragma once
#include <stdio.h>
#include <iostream>
using namespace std;
#ifndef WINDOWS
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>//close()
#include<netinet/in.h>//struct sockaddr_in
#include<arpa/inet.h>//inet_ntoa
#else
#include <WinSock2.h>
#include <WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
#endif
class TCPClient
{
public:
int init_TCPClient(const char *address, int port); //初始化,socket,connect在这里面实现
int sendMsg(const char *Msg, int len); //发数据
private:
struct sockaddr_in my_sockaddr;
#ifndef WINDOWS
int m_sock;
#else
SOCKET m_sock;
#endif
};
********************************类TCPClient中函数的实现(TCPClient.cpp)*************************
#include "TCPClient.h"
int TCPClient::init_TCPClient(const char *address, int port)
{
#ifdef WINDOWS
WSADATA wsaData;
WSAStartup(MAKEWORD(1, 1), &wsaData);
#endif
if ((m_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket failed");
return -1;
}
my_sockaddr.sin_family = AF_INET;
my_sockaddr.sin_port = htons(port); //服务端绑定的端口,8765
if (strcmp(address, "")== 0)
{
my_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); //服务端的IP,不是自己的IP,比如现在本机(客户端)IP是192.168.1.87,服务端IP是192.168.1.23,这里的绑定的IP是服务端端额192.168.1.23
}
else
{
my_sockaddr.sin_addr.s_addr = inet_addr(address);
}
if (connect(m_sock, (sockaddr*)&my_sockaddr, sizeof(my_sockaddr) < 0))
{
perror("connect failed");
return -1;
}
return 0;
}
int TCPClient::sendMsg(const char *Msg, int len)
{
#ifndef WINDOWS
int n = write(m_sock, Msg, len); //Linux下发数据
#else
int n = sendto(m_sock, Msg, len, 0, (sockaddr*)&my_sockaddr, sizeof(my_sockaddr)); //Windows下的发数据函数
#endif
if (n > 0)
{
printf("send messagd \"%d\" success", Msg);
}
return 0;
}
***************再写一个main.cpp*********************************
#include "TCPClient.h"
int main()
{
TCPClient myTCPClient;
if (myTCPClient.init_TCPClient("", 8765) == 0)
{
char *buf = "This is a Client";
myTCPClient.sendMsg(buf, strlen(buf) + 1);
}
getchar();
return 0;
}
这里所有就写好了,一个跨平台TCP网络程序。。。简单吧。。
关于这方面的编程网上的资料真的是太多了。但也不知道是不是大家相互抄袭还是什么,最后编写的的代码基本都是本机对本机通讯的测试代码,根本没有多机之间的通讯,也就是自己的电脑去跟另外一台电脑通讯。我相信每个写出“TCP编程”博客文章的人都掌握了多机通讯,这里为了更好的帮助初学者,在先人基础上,我更加完善一下代码。
TCP肯定有一个服务端和一个客户端,先讲服务端, 流程很简单:
1、初始化(windows平台下必须要这一步,Linux下则没有)
2、socket,创建网络套接字
3、bind,绑定地址跟端口
4、listen,监听
5、accept,接收
6、recv / send (Linux 下为read / write) ,收发数据
掌握这些流程就可以写一个客户端代码了:
我这里是C++编程,但流程是严格按上面6步来的
先建立一个头文件TCPServer.h:
*****************************************分割线**************************************************
#pragma once
#include <stdio.h>
#include <iostream>
using namespace std;
#ifndef WINDOWS //预先定义宏WINDOWS,在Windows vs下项目右键,属性里面添加
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>//close()
#include<netinet/in.h>//struct sockaddr_in
#include<arpa/inet.h>//inet_ntoa
#else
#include <WinSock2.h>
#include <WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
#endif
class TCPServer
{
public:
int init_TCPServer(const char *address, int port); //初始化tcp,socket、bind在这个里面实现
int run(); //listen和accept以及收发数据在这里面
private:
#ifndef WINDOWS
int m_sock; //Linux下套接字类型
#else
SOCKET m_sock; //windows下套接字类型
#endif
};
******************************************类TCPServer中函数的实现(TCPServer.cpp):******************************
#include "TCPServer.h"
int TCPServer::init_TCPServer(const char *address, int port)
{
#ifdef WINDOWS
WSADATA wsaData;
WSAStartup(MAKEWORD(1, 1), &wsaData); //windows下必须要初始化,不然socket会失败
#endif
if ((m_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket failed");
return -1;
}
struct sockaddr_in my_sockaddr;
my_sockaddr.sin_family = AF_INET;
my_sockaddr.sin_port = htons(port); //监听的是本机的端口,不是客户端的端口
if (strcmp(address, "") == 0)
{
my_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); //这是绑定的是自己的IP,跟监听一样,是对本机进行绑定跟监听,不是客户端的,当多机进行通讯时,比如本机是192.168.1.23,客户端是192.168.1.87,这里绑定的是本机的192.168.1.23,而不是客户端的192.168.1.87。但在客户端中,connect中需要给的地址是服务端的,端口也是服务端的
else
{
my_sockaddr.sin_addr.s_addr = inet_addr(address); //跟上面一样
}
if (bind(m_sock, (sockaddr*)&my_sockaddr, sizeof(my_sockaddr)) < 0)
{
perror("bind failed");
return -1;
}
printf("connection...\n");
return 0;
}
int TCPServer::run()
{
if (listen(m_sock, 20) < 0)
{
perror("listen failed");
return -1;
}
struct sockaddr_in my_sockaddr;
#ifndef WINDOWS
int my_recv;
socklen_t len = sizeof(my_sockaddr);
#else
SOCKET my_recv;
int len = sizeof(my_sockaddr);
#endif
while(1)
{
if ((my_recv = accept(m_sock, (sockaddr*)&my_sockaddr, &len)) < 0) //没连接时,函数阻塞
{
perror("accept failed");
return -1;
}
char buf[1024];
memset(buf, 0, sizeof(buf));
#ifndef WINDOWS
int n = read(my_recv, buf, sizeof(buf)); //linux下接受数据函数
#else
int n = recv(my_recv, buf, sizeof(buf), 0); //windows下接受函数
#endif
if (n > 0)
{
printf("recvice from Client: %s\n", buf);
}
}
return 0;
}
*********************************************************************************************
再写一个简单得main.cpp函数
#include "TCPServer.h"
int main()
{
TCPServer myTCPServer;
if (myTCPServer.init_TCPServer("", 8765) == 0)
myTCPServer.run();
return 0;
}
************************************************
服务端就写好了,简单吧,接下来看看服务端的实现,服务端更简单了:
1、初始化 :Windows下必要,Linux下没有
2、socket
3、connect
4、sendto / recv (Linux下为read / write) :收发数据
上代码,先建立头文件,TCPClient.h
*********************************************************
#pragma once
#include <stdio.h>
#include <iostream>
using namespace std;
#ifndef WINDOWS
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>//close()
#include<netinet/in.h>//struct sockaddr_in
#include<arpa/inet.h>//inet_ntoa
#else
#include <WinSock2.h>
#include <WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
#endif
class TCPClient
{
public:
int init_TCPClient(const char *address, int port); //初始化,socket,connect在这里面实现
int sendMsg(const char *Msg, int len); //发数据
private:
struct sockaddr_in my_sockaddr;
#ifndef WINDOWS
int m_sock;
#else
SOCKET m_sock;
#endif
};
********************************类TCPClient中函数的实现(TCPClient.cpp)*************************
#include "TCPClient.h"
int TCPClient::init_TCPClient(const char *address, int port)
{
#ifdef WINDOWS
WSADATA wsaData;
WSAStartup(MAKEWORD(1, 1), &wsaData);
#endif
if ((m_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket failed");
return -1;
}
my_sockaddr.sin_family = AF_INET;
my_sockaddr.sin_port = htons(port); //服务端绑定的端口,8765
if (strcmp(address, "")== 0)
{
my_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); //服务端的IP,不是自己的IP,比如现在本机(客户端)IP是192.168.1.87,服务端IP是192.168.1.23,这里的绑定的IP是服务端端额192.168.1.23
}
else
{
my_sockaddr.sin_addr.s_addr = inet_addr(address);
}
if (connect(m_sock, (sockaddr*)&my_sockaddr, sizeof(my_sockaddr) < 0))
{
perror("connect failed");
return -1;
}
return 0;
}
int TCPClient::sendMsg(const char *Msg, int len)
{
#ifndef WINDOWS
int n = write(m_sock, Msg, len); //Linux下发数据
#else
int n = sendto(m_sock, Msg, len, 0, (sockaddr*)&my_sockaddr, sizeof(my_sockaddr)); //Windows下的发数据函数
#endif
if (n > 0)
{
printf("send messagd \"%d\" success", Msg);
}
return 0;
}
***************再写一个main.cpp*********************************
#include "TCPClient.h"
int main()
{
TCPClient myTCPClient;
if (myTCPClient.init_TCPClient("", 8765) == 0)
{
char *buf = "This is a Client";
myTCPClient.sendMsg(buf, strlen(buf) + 1);
}
getchar();
return 0;
}
这里所有就写好了,一个跨平台TCP网络程序。。。简单吧。。