如果想要实现两不同局域网之间的主机进程通信,即实现局域网内两个电脑之间的数据传输,那么就不能通过管道或者命名管道的方式来实现,这里的局域网通信是通过一种叫做socket套接字的方式来实现。
首先想要与同一局域网内部的另一个电脑进行数据传输,需要知道它的IP地址,因为IP是连接网络之后分配给个人主机的唯一标识,所以先找到想要建立连接的主机的地址,然后我们双方共同约定一个类似于管道的唯一出入口(也就是端口号port),这里的端口号一般分为公认端口号和注册端口号,约定好端口号传输的时候双方都需要遵守共同的网络协议(TCP(SOCK_STREAM),UDP(SOCK_DRAM),ICMP(SOCK_RAW))。
公认端口号:知名端口即众所周知的端口号,范围从0到1023,这些端口号一般固定分配给一些服务。比如21端口分配给FTP(文件传输协议)服务,25端口分配给SMTP(简单邮件传输协议)服务,80端口分配给HTTP服务,135端口分配给RPC(远程过程调用)服务等等
注册端口号:端口号从1025到49151。它们松散地绑定于一些服务。也是说有许多服务绑定于这些端口,这些端口同样用于许多其他目的。这些端口多数没有明确的定义服务对象,不同程序可根据实际需要自己定义,如后面要介绍的远程控制软件和木马程序中都会有这些端口的定义的。记住这些常见的程序端口在木马程序的防护和查杀上是非常有必要的。常见木马所使用的端口在后面将有详细的列表
一般选择端口号都是选择注册端口号,没有明确的定义 服务对象,不同的通信可以根据自己的需要进行定义。
实现过程如下:
server:
- #include <arpa/inet.h>//包含socket函数使用的各种协议族,send(),recv()
- #include <unistd.h>//调用linux系统函数的头文件(read(),write(),send(),select())
- #include <iostream>
- #include <thread>
- #include <list>
- #define PORT 7000
- #define IP "127.0.0.1"
-
- int s;
- struct sockaddr_in servaddr;
- socklen_t len;
- std::list<int> li;
-
- void getConn() {
- while(1){
- int conn = accept(s, (struct sockaddr*)&servaddr, &len);
- li.push_back(conn);
- printf("%d\n", conn);
- }
- }
-
- void getData() {
- struct timeval tv;
- tv.tv_sec = 2;
- tv.tv_usec = 0;
- while(1) {
- std::list<int>::iterator it;
- for(it=li.begin(); it!=li.end(); ++it){
- fd_set rfds;
- FD_ZERO(&rfds);
- int maxfd = 0;
- int retval = 0;
- FD_SET(*it, &rfds);
- if(maxfd < *it){
- maxfd = *it;
- }
- retval = select(maxfd+1, &rfds, NULL, NULL, &tv);
- if(retval == -1){
- printf("select error\n");
- }else if(retval == 0) {
- }else{
- char buf[1024];
- memset(buf, 0 ,sizeof(buf));
- long len = recv(*it, buf, sizeof(buf), 0);
- printf("%s", buf);
- }
- }
- sleep(1);
-
- }
- }
-
- void sendMess() {
- while(1) {
- char buf[1024];
- fgets(buf, sizeof(buf), stdin);
- std::list<int>::iterator it;
- for(it=li.begin(); it!=li.end(); ++it){
- send(*it, buf, sizeof(buf), 0);
- }
- }
- }
-
- int main() {
- s = socket(AF_INET, SOCK_STREAM, 0);
- memset(&servaddr, 0, sizeof(servaddr));
- servaddr.sin_family = AF_INET;
- servaddr.sin_port = htons(PORT);
- servaddr.sin_addr.s_addr = inet_addr(IP);
- if(bind(s, (struct sockaddr* ) &servaddr, sizeof(servaddr))==-1) {
- perror("bind");
- exit(1);
- }
- if(listen(s, 20) == -1) {
- perror("listen");
- exit(1);
- }
- len = sizeof(servaddr);
- std::thread t(getConn);
- t.detach();
- std::thread t1(sendMess);
- t1.detach();
- std::thread t2(getData);
- t2.detach();
- while(1){
-
- }
- return 0;
- }
client:
- #include <arpa/inet.h>
- #include <unistd.h>
- #include <iostream>
- #define MYPORT 7000
- #define BUFFER_SIZE 1024
- int main(int argc,char *argv[])
- {
- int sock_cli;
- fd_set rfds;
- struct timeval tv;
- int retval, maxfd;
-
-
- sock_cli = socket(AF_INET,SOCK_STREAM, 0);
-
- struct sockaddr_in servaddr;
- memset(&servaddr, 0, sizeof(servaddr));
- servaddr.sin_family = AF_INET;
- char s[1024];
- int a;
- std::cout << "输入想要建立连接的端口号以及IP地址:" << std::endl;
- scanf("%d",&a);
- getchar();
- scanf("%s",s);
- servaddr.sin_port = htons(a);
- servaddr.sin_addr.s_addr = inet_addr(s);
-
-
- if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
- {
- perror("connect");
- exit(1);
- }
-
- while(1){
-
- FD_ZERO(&rfds);
-
- FD_SET(0, &rfds);
- maxfd = 0;
-
- FD_SET(sock_cli, &rfds);
-
- if(maxfd < sock_cli)
- maxfd = sock_cli;
-
- tv.tv_sec = 5;
- tv.tv_usec = 0;
-
- retval = select(maxfd+1, &rfds, NULL, NULL, &tv);
- if(retval == -1){
- printf("select出错,客户端程序退出\n");
- break;
- }else if(retval == 0){
- printf("客户端没有任何输入信息,并且服务器也没有信息到来,waiting...\n");
- continue;
- }else{
-
- if(FD_ISSET(sock_cli,&rfds)){
- char recvbuf[BUFFER_SIZE];
- long len;
- len = recv(sock_cli, recvbuf, sizeof(recvbuf),0);
- printf("%s", recvbuf);
- memset(recvbuf, 0, sizeof(recvbuf));
- }
-
- if(FD_ISSET(0, &rfds)){
- char sendbuf[1024];
-
- fgets(sendbuf, sizeof(sendbuf), stdin);
- send(sock_cli, sendbuf, strlen(sendbuf),0);
- memset(sendbuf, 0, sizeof(sendbuf));
- }
- }
- }
-
- close(sock_cli);
- return 0;
- }