使用之前的函数实现的简单聊天程序

TCP协议

双方实时发送/接收消息

实现后的问题:

  可能是我虚拟机的IP地址配得有问题吧。在一台电脑上面开两个终端,用127.0.0.1的IP收发可以互通。但是两个虚拟机就不行了,用192.168的IP段,能够ping通但是代码接收不到消息。

  还有,两个进程都是接收到消息后,需要我自己按一下回车才能发送消息。

服务器端代码:

#include<stdio.h>
#include<string.h>
#include<errno.h>
#include<sys/socket.h>
#include<resolv.h>
#include<stdlib.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#define MAXBUF 1024
int main(int argc, char *argv[])
{
int pid;
int sockfd, new_fd;
socklen_t len;
struct sockaddr_in my_addr, their_addr;
unsigned int myport, lisnum;
char buf[MAXBUF + ];
if(argv[])
myport = atoi(argv[]); //命令行字符串转为整数,端口
else
myport = ; //默认端口 if(argv[])
lisnum = atoi(argv[]); //监听队列的大小
else
lisnum = ; //创建socket对象, IPv4, TCP, 默认协议
if((sockfd = socket(AF_INET, SOCK_STREAM, )) == -) //创建socket对象
{
perror("socket");
exit(EXIT_FAILURE);
} bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = AF_INET; //地址协议
my_addr.sin_port = htons(myport); //地址端口
if(argv[])
my_addr.sin_addr.s_addr = inet_addr(argv[]); //指定IP地址 从点分十进制字符串转为32位二进制
else
my_addr.sin_addr.s_addr = INADDR_ANY; //否则设置为本机任意地址 char mybuf[];
inet_ntop(AF_INET, &my_addr.sin_addr.s_addr, mybuf, );
printf("the ip is '%s'\n", mybuf);
//绑定地址信息
if(bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -)
{
perror("bind");
exit(EXIT_FAILURE);
} //监听网络
if(listen(sockfd, lisnum) == -)
{
perror("listen");
exit(EXIT_FAILURE);
}
printf("wait for connect\n");
len = sizeof(struct sockaddr); //阻塞等待连接
if((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &len)) == -)
{
perror("accept");
exit(EXIT_FAILURE);
}
else //打印接收到的信息
{
printf("server: got connection from %s, port %d, socket %d\n", inet_ntoa(their_addr.sin_addr), ntohs(their_addr.sin_port), new_fd);
} //创建新进程
if(- == (pid = fork()))
{
perror("fork");
exit(EXIT_FAILURE);
}
else if( == pid) //子进程用于发送消息
{
while()
{
bzero(buf, MAXBUF + );
printf("input the message to send:");
fgets(buf, MAXBUF, stdin);
if(!strncasecmp(buf, "quit", ))
{
printf("i will close the connect!\n");
break;
}
len = send(new_fd, buf, strlen(buf) - , );
if(len < )
{
printf("message '%s' send failure! errno code is %d, errno message is '%s'\n", buf, errno, strerror(errno));
break;
}
}
}
else //父进程用于接收消息
{
while()
{
bzero(buf, MAXBUF + );
len = recv(new_fd, buf, MAXBUF, );
if(len > )
{
printf("message recv successful : '%s', %dByte recv\n", buf, len);
}
else if(len < )
{
printf("recv failure! errno code is %d, errno message is '%s'\n", errno, strerror(errno));
break;
}
else
{
printf("the other one close quit\n");
break;
}
}
} close(new_fd);
close(sockfd);
return ;
}

客户端代码:

#include<stdio.h>
#include<string.h>
#include<errno.h>
#include<sys/socket.h>
#include<resolv.h>
#include<stdlib.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#define MAXBUF 1024
int main(int argc, char **argv)
{
int sockfd, len;
struct sockaddr_in dest;
char buffer[MAXBUF + ];
if(argc != )
{
printf(" error format, it must be :\n \t\t%s IP port\n", argv[]);
exit(EXIT_FAILURE);
} //创建socket对象
if((sockfd = socket(AF_INET, SOCK_STREAM, )) < )
{
perror("Socket");
exit(errno);
}
printf("socket created\n");
bzero(&dest, sizeof(dest));
dest.sin_family = AF_INET; //地址协议
dest.sin_port = htons(atoi(argv[])); //对方端口
//对方IP地址
if(inet_aton(argv[], (struct in_addr *)&dest.sin_addr.s_addr) == )
{
perror("argv[1]");
exit(errno);
}
//发起连接
if(connect(sockfd, (struct sockaddr *)&dest, sizeof(dest)) == -)
{
perror("Connect");
exit(errno);
}
printf("server connected\n");
pid_t pid; //创建子进程
if(- == (pid = fork()))
{
perror("fork");
exit(errno);
}
else if(pid == ) //子进程用于数据接收
{
while()
{
bzero(buffer, MAXBUF + );
len = recv(sockfd, buffer, MAXBUF, );
if(len > )
{
printf("recv successful:'%s', %d byte recv\n", buffer, len);
}
else if(len < )
{
perror("recv");
break;
}
else
{
printf("the other one close, quit\n");
break;
}
}
}
else //父进程用于数据发送
{
while()
{
bzero(buffer, MAXBUF + );
printf("input the message to send:");
fgets(buffer, MAXBUF, stdin);
if(!strncasecmp(buffer, "quit", ))
{
printf("i will close the connect!\n");
break;
}
len = send(sockfd, buffer, strlen(buffer) - , );
if(len < )
{
printf("message '%s' send failure! errno code is %d, errno message is '%s'\n", buffer, errno, strerror(errno));
break;
}
}
}
close(sockfd);
return ;
}

【linux高级程序设计】(第十三章)Linux Socket网络编程基础 3的更多相关文章

  1. 【linux高级程序设计】(第十三章)Linux Socket网络编程基础 2

    BSD Socket网络编程API 创建socket对象 int socket (int __domain, int __type, int __protocol) :成功返回socket文件描述符, ...

  2. Socket网络编程-基础篇

    Socket网络编程 网络通讯三要素: IP地址[主机名] 网络中设备的标识 本地回环地址:127.0.0.1 主机名:localhost 端口号 用于标识进程的逻辑地址 有效端口:0~65535 其 ...

  3. python全栈开发从入门到放弃之socket网络编程基础

    网络编程基础 一 客户端/服务器架构 1.硬件C/S架构(打印机) 2.软件C/S架构 互联网中处处是C/S架构 如黄色网站是服务端,你的浏览器是客户端(B/S架构也是C/S架构的一种) 腾讯作为服务 ...

  4. 第九章:Python の 网络编程基础(一)

    本課主題 何为TCP/IP协议 初认识什么是网络编程 网络编程中的 "粘包" 自定义 MySocket 类 本周作业 何为TCP/IP 协议 TCP/IP协议是主机接入互网以及接入 ...

  5. 【linux高级程序设计】(第十三章)Linux Socket网络编程基础 4

    网络调试工具 tcpdump 功能:打印指定网络接口中与布尔表达式匹配的报头信息 关键字: ①类型:host(默认).net.port host 210.27.48.2 //指明是一台主机 net 2 ...

  6. 【linux高级程序设计】(第十三章)Linux Socket网络编程基础

    IP地址定义: struct in_addr{ __u32 s_addr; }; in_addr_t  inet_addr (__const char * __cp) :把点分十进制IP地址字符串转换 ...

  7. 第十三章:Python の 网络编程进阶(二)

    本課主題 SQLAlchemy - Core SQLAlchemy - ORM Paramiko 介紹和操作 上下文操作应用 初探堡垒机 SQLAlchemy - Core 连接 URL 通过 cre ...

  8. 第十三篇:socket网络编程

    本篇主要介绍网络编程的基础,以及UDP/TCP网络的socket编程,关于UDP套接字聊天器的实现.以及基于TCP套接字的服务器/客户端的实现上传下载功能. 一.网络通信 关于网络通信即通过网络(介质 ...

  9. socket网络编程基础小记

    "一切皆Socket!" 话虽些许夸张.可是事实也是,如今的网络编程差点儿都是用的socket. --有感于实际编程和开源项目研究. 我们深谙信息交流的价值,那网络中进程之间怎样通 ...

  10. java架构《Socket网络编程基础篇》

    本章主要介绍Socket的基本概念,传统的同步阻塞式I/O编程,伪异步IO实现,学习NIO的同步非阻塞编程和NIO2.0(AIO)异步非阻塞编程. 目前为止,Java共支持3种网络编程模型:BIO.N ...

随机推荐

  1. notepad++ 换行技巧 log换行

    有时候,服务器收集上来的日志,格式很乱,看log很难,如下: java.lang.IllegalStateException: BEvent.init() must be call first\n\t ...

  2. nodejs基础1

    nodejs学习网站: https://github.com/alsotang/node-lessons 1.全局对象 (1)node中没有window对象,有global对象替代window对象 g ...

  3. laravel5.5用户认证源码分析

    目录 1. 生成相关文件和配置 2. 分析路由文件 3. 以登陆开始为例,分析auth到底是怎么工作的 3.1 分析登录文件 3.2 分析门面Auth. 1. 生成相关文件和配置 快速生成命令 php ...

  4. 关于main与wmain函数

    最近写一个控制台程序,并且希望该控制台程序运行时不显示控制台窗口,于是在程序include语句下面加入如下代码 #pragma comment (linker,"/subsystem:\&q ...

  5. 【Soft-Margin Support Vector Machine】林轩田机器学习技术

    Hard-Margin的约束太强了:要求必须把所有点都分开.这样就可能带来overfiiting,把noise也当成正确的样本点了. Hard-Margin有些“学习洁癖”,如何克服这种学习洁癖呢? ...

  6. paramiko类Fabric主机管理

    环境:Linux python3.5 要求:类 Fabric 主机管理程序开发:1. 运行程序列出主机组或者主机列表2. 选择指定主机或主机组3. 选择让主机或者主机组执行命令或者向其传输文件(上传/ ...

  7. java初学1

    1.Java主要技术和分支以及应用领域 (1)Java SE Java Platform,Standard Edition,Java SE 以前称为J2SE.它允许开发和部署在桌面.服务器.嵌入式环境 ...

  8. Python全栈工程师(迭代器、字节串)

    ParisGabriel                每天坚持手写  一天一篇  决定坚持几年 为了梦想为了信仰     Python人工智能从入门到精通 迭代器 Iterator: 用<&g ...

  9. 【bzoj4940】[Ynoi2016]这是我自己的发明 DFS序+树上倍增+莫队算法

    题目描述 给一个树,n 个点,有点权,初始根是 1. m 个操作,每次操作: 1. 将树根换为 x. 2. 给出两个点 x,y,从 x 的子树中选每一个点,y 的子树中选每一个点,如果两个点点权相等, ...

  10. 【BZOJ1123】 [POI2008]BLO (tarjan)

    tarjan判断割点...拿掉一个点之后,会被分成若干个联通块,用节点个数和统计一下他们相互不能到达的个数就好. ; maxm=; type edgetype=record toward,next:l ...