北大侠客行MUD论坛

 找回密码
 注册
搜索
热搜: 新手 wiki 升级
查看: 18014|回复: 12

好东西,大家分享!一切的基础啊!

[复制链接]
发表于 2011-5-28 15:07:40 | 显示全部楼层 |阅读模式
一切的基础,不说了~~~大爱!


  1. #include
  2. #include
  3. #include
  4. #include
  5. #include
  6. #include
  7. #include
  8. #include
  9. #include
  10. #include

  11. #define MAX_PARAMTER 3  //参数个数
  12. /*TELNET命令*/
  13. #define IAC 255    //TELNET协商语句以此开头
  14. #define WILL 251   //请求本方动作,应答同意要求本方
  15. #define WONT 252   //请求本方不动作,应答不同意本方动作或同意本方不动作
  16. #define DO   253   //请求对方动作,应答同意对方要求动作
  17. #define DONT 254   //请求对方不动作,应答不同意对方要求动作或同意对方不动作
  18. /*TELNET选项*/
  19. #define ECHO 1                //TELNET回显选项,TELNET协商语句以此为最后一部分(子协议除外)

  20. #define NEGONATION_LENTH 3 //TELNET协商语句长度

  21. #define MAX_COMMAND 1024  //终端输入最大长度
  22. #define MAX_RECEIVE 1024  //接收最大长度
  23. #define MAX_SEND    1024  //发送最大长度

  24. /*用于区别是发来的请求还是应答(由于请求应答相同有对称性)*/
  25. #define SERVER_ECHO_ON  1 //已成为服务器回显状态
  26. #define SERVER_ECHO_OFF 0 //还未成服务器为回显状态

  27. #define STD_IN 0  //标准输入输出文件描述符

  28. unsigned char echo_status = 0; //回显状态
  29. int sockfd = -1;  //SOCKET文件描述
  30. int telnet_connect = 0; //TELNET通断控制变量

  31. int init_socket(char* server_ip, char * server_port)
  32. {
  33.         sockfd = socket(AF_INET, SOCK_STREAM, 0); //参数1为IPV4,参数2为TCP链接,参数3固定为0
  34.        
  35.         if (sockfd < 0)
  36.         {
  37.                 printf("Socket error\n");
  38.                 return -1;
  39.         }

  40.         struct sockaddr_in server_addr;  //服务器地址信息
  41.        
  42.         bzero(&server_addr, sizeof(server_addr));  //清空server_addr

  43.         server_addr.sin_family = AF_INET;            //IPV4
  44.         server_addr.sin_addr.s_addr = inet_addr(server_ip);     //服务器IP地址
  45.         server_addr.sin_port = htons((unsigned short)(atoi(server_port)));   //服务器端口
  46.         /*
  47.         if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)  //一般服务器需要绑定,客户端其实不需要绑定,绑定是绑定自己不是绑定服务器
  48.         {
  49.                 printf("Bind error\n");
  50.                 return -1;
  51.         }
  52.         */
  53.         if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)   //与服务器取得链接
  54.         {
  55.                 printf("Connect error\n");
  56.                 return -1;
  57.         }

  58.         telnet_connect = 1;
  59.         return 0;
  60. }

  61. int deal_telnet_protocol(unsigned char* receive_server)
  62. {
  63.         unsigned char client_send[NEGONATION_LENTH];
  64.         int i = 0;

  65.         client_send[0] = receive_server[0];   //IAC
  66.         client_send[2] = receive_server[2];   //服务器要求的选项

  67.         switch (receive_server[1])
  68.         {
  69.                 case WILL:                                //如果收到服务器要求改变状态
  70.                         {
  71.                                 if (receive_server[2] == ECHO)     //查看选项是否为回显
  72.                                 {
  73.                                         if (echo_status == SERVER_ECHO_OFF)   //查看现在的服务器ECHO状态,通过使用状态位判断服务器发来的为请求还是应当,因为telnet的请求命令和应答都相同有对称性(由于客户端没发生过请求,服务器端也就不会发应答,发来的数据都是请求,其实不用判断)
  74.                                         {                                                         //如果现在是服务器回显状态,则ECHO的状态没有改变,不发送应答,如果不是服务器回显状态,则ECHO的状态改变了,发送应答
  75.                                                 client_send[1] = DO;             //同意服务器端开启ECHO选项
  76.                                                 echo_status = SERVER_ECHO_ON;  //修改服务器ECHO状态为ON
  77.                                         }
  78.                                         else
  79.                                         {
  80.                                                 return 0;                 //否则不应答
  81.                                         }
  82.                                 }
  83.                                 else                              //其他服务器端选项都不同意,因为客户端从没有向服务器发送命令,
  84.                                 {                                 //因此服务器发来的数据不可能是应答,都是请求,因此其实不需要判断状态
  85.                                         client_send[1] = DONT;        
  86.                                 }
  87.                                 break;
  88.                         }
  89.                 case WONT:
  90.                         {
  91.                                 if (receive_server[2] == ECHO)  //查看选项是否为回显
  92.                                 {
  93.                                         if (echo_status == SERVER_ECHO_ON) //现在状态是否为ON
  94.                                         {
  95.                         client_send[1] = DONT;
  96.                                                 echo_status = SERVER_ECHO_OFF;
  97.                                         }
  98.                                         else
  99.                                         {
  100.                                                 return 0;               //否则不应答
  101.                                         }

  102.                                 }
  103.                                 else                           //WONT如果要回复只能用DONT
  104.                                 {
  105.                                         client_send[1] = DONT;         
  106.                                 }
  107.                                 break;
  108.                         }
  109.                 case DO:                               //其余的要求客户端做的选项都拒绝
  110.                         {
  111.                                 client_send[1] = WONT;         
  112.                                 break;
  113.                         }
  114.                 case DONT:                             //DONT选项只能用WONT来应答
  115.                         {
  116.                                 client_send[1] = WONT;         
  117.                                 break;
  118.                         }
  119.                 default:
  120.                         {
  121.                                 printf("Receive error telnet command\n");
  122.                                 return -1;
  123.                         }
  124.         }
  125.        
  126.         if (send(sockfd, client_send, NEGONATION_LENTH, 0) < 0) //发送应答数据包
  127.         {
  128.                 printf("send ack error\n");
  129.                 return -1;
  130.         }

  131.         printf("\n+++++++++++++send+++++++++++++++\n");
  132.         for (i = 0; i < NEGONATION_LENTH; i++)
  133.         {
  134.                 printf("%d.[%d<%c>] ", i, client_send[i], client_send[i]);
  135.         }
  136.         printf("\n++++++++++++++++++++++++++++++++\n");
  137.        
  138.         return 0;
  139. }

  140. int  cs_communcate(void)
  141. {
  142.         int re_recv = -1;
  143.         int i = 0;
  144.         int deal_lenth = 0;   //处理的数据长度
  145.         unsigned char* p_server = NULL; //指向手到服务器数据的指针

  146.         unsigned char server_data[MAX_RECEIVE];         //接收到的服务数据
  147.         unsigned char server_negonation[NEGONATION_LENTH];
  148.        
  149.         re_recv = recv(sockfd, server_data, MAX_RECEIVE, 0); //接收服务器发来的数据
  150.        
  151.         if (re_recv > 0)
  152.         {
  153.                 printf("\n-------------receive-------------\n");
  154.                 for(i = 0; i < re_recv; i++)
  155.                 {
  156.                         printf("%d.[%d<%c>] ", i, server_data[i], server_data[i]);
  157.                         if (!((i + 1) % 4))
  158.                         {
  159.                                 printf("\n");
  160.                         }
  161.                 }
  162.                 printf("\n-------------------------------\n\n");

  163.                 deal_lenth = 0;
  164.                 p_server = server_data;
  165.                 while (deal_lenth < re_recv)
  166.                 {
  167.                         if ((*p_server == IAC) && (*(p_server + 1) != IAC) )   //判断接收到的是否为协商语句(请求或应答,实际上因client未发送请求所以不可能为应答)
  168.                         {
  169.                                 memcpy(server_negonation, p_server, NEGONATION_LENTH); //缓存协商语句
  170.                                 deal_telnet_protocol(server_negonation);  //处理每条服务器发来的协商语句

  171.                                 p_server += NEGONATION_LENTH;
  172.                                 deal_lenth += NEGONATION_LENTH;
  173.                         }
  174.                         else                                                 //如果是服务器发来的数据则把它显示到终端上
  175.                         {
  176.                                 write(STD_IN, p_server, strlen(p_server) + 1);
  177.                                 deal_lenth = re_recv;                            //认为收到的如果为数据则它在一包的最后,或者独立为一包数据
  178.                         }
  179.                 }       

  180.         }

  181.         return 0;
  182.        
  183. }

  184. int send_usrcommand()
  185. {
  186.         int i = 0;
  187.         char usr_command[MAX_COMMAND];  //终端发送的用户命令(不是TELNET协议中的命令)

  188.         if (read(STD_IN, usr_command, MAX_COMMAND) > 0) //如果读取用户命令成功则将其发送给服务器
  189.         {
  190.                 fflush(stdout);  //清空输出缓冲区的内容,这样用户可以一次发送带空格的命令

  191.                 if (!strcmp(usr_command, "exit\n"))    //如果输入字符串为exit则断开TELNET控制连接
  192.                 {
  193.                                 telnet_connect = 0;
  194.                                 close(sockfd);
  195.                                 return 0;
  196.                 }

  197.                 if (send(sockfd, usr_command, strlen(usr_command) - 1, 0) < 0) //发送命令但不发送回车符
  198.                 {
  199.                         printf("Send usr command error\n");
  200.                         return -1;
  201.                 }

  202.             printf("\n+++++++++++++send+++++++++++++++\n");
  203.                 for(i = 0; i < strlen(usr_command) - 1; i++)   
  204.                 {
  205.                         printf("%d.[%d<%c>] ", i, usr_command[i], usr_command[i]);
  206.                         if (!((i + 1) % 4))
  207.                         {
  208.                                 printf("\n");
  209.                         }
  210.                 }
  211.                 printf("\n++++++++++++++++++++++++++++++++\n");

  212.                 if (send(sockfd, "\r\n", 2, 0) < 0)   //NVT中以换行回车作为一个命令的结束(NVT用于在TELNET中连接不同操作系统,nvtasc码的转换由操作系统实现)
  213.                 {
  214.                         printf("Send usr command error\n");
  215.                         return -1;
  216.                 }
  217.                
  218.                 printf("\n+++++++++++++send+++++++++++++++\n");
  219.                 printf("%d.[%d<%c>]  %d.[%d<%c>]", '\n', '\r');
  220.                 printf("\n++++++++++++++++++++++++++++++++\n");
  221.         }

  222.         return 0;
  223. }

  224. int main(int argc, char** argv)
  225. {
  226.         if (argc != MAX_PARAMTER)
  227.         {
  228.                 printf("2 parameters please\n");
  229.                 return -1;
  230.         }

  231.         if (init_socket(argv[1], argv[2]) < 0)
  232.         {
  233.                 return -1;
  234.         }

  235.         fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK); //设置SOCKET文件为非阻塞方式
  236.         fcntl(STD_IN, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK); //设置标准输入文件为非阻塞方式

  237.         while (telnet_connect)  //当将sockfd和标准输入输出STD_IN设置为非阻塞后,如果一方收到数据则继续接收,如果两方都收不到数据则效果为等待从键盘输入数据何等待接收
  238.         {
  239.                 if(cs_communcate() < 0)  //处理服务发来的数据
  240.                 {
  241.                         close(sockfd);
  242.                         return -1;
  243.                 }

  244.                 if (send_usrcommand() < 0) //处理终端用户发来的命令
  245.                 {
  246.                         close(sockfd);
  247.                         return -1;
  248.                 }
  249.         }

  250.         return 0;
  251. }
复制代码





有了这个东西····哈哈哈哈哈哈哈哈
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
发表于 2011-5-28 15:11:25 | 显示全部楼层
转移一下版块
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
发表于 2011-5-28 15:16:06 | 显示全部楼层

回复 3楼 的帖子

mud最底层的网络连接模块
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
发表于 2011-5-28 15:16:27 | 显示全部楼层
这学期在学网络基础,勉强能看懂
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
发表于 2011-5-28 15:18:46 | 显示全部楼层
蒹葭哪里弄到的代码??
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
 楼主| 发表于 2011-5-28 15:23:04 | 显示全部楼层
网上找的啊~~~

这个是我一切的基础

而且,这个代码,简洁明了,注释丰富~~~

有助我成就“阴谋”
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
发表于 2011-5-28 16:19:59 | 显示全部楼层
为啥这么激动啊,随便找个脚本语言,python啥的telnet库都是现成的。。。
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
发表于 2011-5-28 16:42:22 | 显示全部楼层
这不是linux socket编程嚒
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
发表于 2011-5-28 16:45:56 | 显示全部楼层
JIZONG 好激动。。。
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
发表于 2011-5-28 18:37:09 | 显示全部楼层
#后面的应该都是注释掉的.

这个代码唯一的闪光点是注释非常多且详细
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|北大侠客行MUD ( 京ICP备16065414号-1 )

GMT+8, 2024-4-26 03:50 PM , Processed in 0.012182 second(s), 14 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表