学习笔记之Linux网络编程入门

本文不涉及太多原理性的记录,纯属从代码入手解析,个人的理解。

【基本知识】TCP协议与UDP协议数据传输方式(本笔记只了解TCP协议)

1.网络中两台主机之间的数据传输方式主要有两种:面向连接TCP,可靠的和面向无连接UDP,不可靠的。

eg:UDP传输:qq视频聊天就是采用UDP传输的;假如是TCP传输,当你网络差时(由于TCP的传输是面向连接、可靠的),所以会导致下一帧视频显示时间往后推,导致聊天对象所看到的画面是不实时的,所以,视频聊天采用UDP传输。

TCP:你传输的文件是采用TCP方式传输的,毕竟你不想得到数据是不完整的。

2.数据传输3要素:目的,源,长度


【代码解剖】

【server.c】

#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>

/* 1.socket

 *2.设置本地地址信息
 * 3.bind
 * 4.listen
 * 5.accept
 * 6.send/recv
 */


#define SERVER_PORT 8888
#define BACKLOG     10

int main(int argc, char **argv)
{
int iSocketServer;
int iSocketClient;
struct sockaddr_in tSocketServerAddr;/* 设置本地地址信息 */
struct sockaddr_in tSocketClientAddr;
int iRet;
int iAddrLen;

int iRecvLen;
unsigned char ucRecvBuf[1000];

int iClientNum = -1;


/*防止僵死进程:方法一,我们把这个信号忽略

         *服务器采用了fork的话,要收集垃圾进程,防止僵尸进程的产生,可以这样处理: 

     *signal(SIGCHLD,SIG_IGN); 交给系统init去回收。 
     *这里子进程就不会产生僵尸进程了。 

         */


/* 1. 获得套接字描述符 */
iSocketServer = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == iSocketServer)
{
printf("socket error!\n");
return -1;
}

/* 2.设置本地地址信息 */
tSocketServerAddr.sin_family      = AF_INET;/* 协议族 */
tSocketServerAddr.sin_port        = htons(SERVER_PORT);  /* host to net, short 端口*/
  tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;/* 本机上的所有ip*/
memset(tSocketServerAddr.sin_zero, 0, 8);/* 填充0 */
/* bzero(&(tSocketServerAddr.sin_zero),8) */

/* 3.绑定地址到套接字上描述符上 */
iRet = bind(iSocketServer, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));
if (-1 == iRet)
{
printf("bind error!\n");
return -1;
}

/* 4.在地址端口上监听 */
iRet = listen(iSocketServer, BACKLOG);
if (-1 == iRet)
{
printf("listen error!\n");
return -1;
}

while (1)
{
iAddrLen = sizeof(struct sockaddr);
iSocketClient = accept(iSocketServer, (struct sockaddr *)&tSocketClientAddr, &iAddrLen);
/*accept 的返回值是客户端的套接字描述符
 *参数1:本机套接字文件描述符 
 *参数2:客户端的ip  地址保存的地方
 *参数3:长度
 * 这个函数处于阻塞状态,等待客户机的连接,接受请求
 */
if (-1 != iSocketClient)
{
iClientNum++;/* 统计客户机的个数 */
/* 打印出连接数,以及客户端的ip  地址 */
printf("Get connect from client %d : %s\n",  iClientNum, inet_ntoa(tSocketClientAddr.sin_addr));

      /* 创建一个子进程复制出一个完全一样的A` 程序
       *如果fork()  创建成功,则子进程会走这条分支
       *父进程会走else  分支

       *创建子进程,在这里仅仅为了了解该知识点

           */
if (!fork())
{
/* 子进程的源码 */
while (1)
{
/* 5.接收客户端发来的数据并保存在ucRecvBuf */
iRecvLen = recv(iSocketClient, ucRecvBuf, 999, 0);
if (iRecvLen <= 0)
{

/* 假设客户端没有发数据,则关闭监听 */
close(iSocketClient);
return -1;
}
else
{

/* 有数据则打印出来 */
ucRecvBuf[iRecvLen] = '\0';
printf("Get Msg From Client %d: %s\n", iClientNum, ucRecvBuf);
}
}
}
/* 父进程 */

  /*防止进程僵死方法二:
 
 *else
 
 * wait(NULL);
 
 *假如你要看进程退出状态的话,则
 
 *else{
 * wait(&status);/* status 子进程结束时返回的终止状态 */
 * if(WIFEXITED(status))/* 正常退出 */
 
 * printf("exit status : %d\n",WIFEXITED(status));
 
 * if(WIFSIGNALED(status))/* 子进程被某个信号终止 */
 * printf("signal number : %d\n",WIFSIGNALED(status)); 
 *}
 *
/
}
}
close(iSocketServer);
return 0;
}

【client.c】
#include <sys/types.h> 
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>

/* socket :创建套接字
 * connect:向服务器发送连接
 * tSocketServerAddr:设置服务器的地址结构
 * send/recv :接受/发送信息
 */

#define SERVER_PORT 8888

int main(int argc, char **argv)
{
int iSocketClient;
struct sockaddr_in tSocketServerAddr;

int iRet;
unsigned char ucSendBuf[1000];
int iSendLen;

if (argc != 2)
{
printf("Usage:\n");
printf("%s <server_ip>\n", argv[0]);
return -1;
}

iSocketClient = socket(AF_INET, SOCK_STREAM, 0);

tSocketServerAddr.sin_family      = AF_INET;/* 协议族 */
tSocketServerAddr.sin_port        = htons(SERVER_PORT);  /* host to net, short 端口*/
  //tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;

  if (0 == inet_aton(argv[1], &tSocketServerAddr.sin_addr))/* 把ip  地址字符串转换 struct in_addr  类型,并存储在tSocketServerAddr.sin_addr*/
  {
  /* 不成功 非法服务器ip  */
printf("invalid server_ip\n");
return -1;
}
memset(tSocketServerAddr.sin_zero, 0, 8);

/* 客户端向服务端发起连接请求 */

/* iSocketClient文件标识符,句柄 ;tSocketServerAddr 保存服务器地址端口等信息;sockaddr):长度*/
iRet = connect(iSocketClient, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));
if (-1 == iRet)
{
printf("connect error!\n");
return -1;
}

while (1)
{
/* 从标准输入那儿获得数据 */
if (fgets(ucSendBuf, 999, stdin))
{
/* 发送数据 */
iSendLen = send(iSocketClient, ucSendBuf, strlen(ucSendBuf), 0);
if (iSendLen <= 0)
{
close(iSocketClient);
return -1;
}
}
}
return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值