一、系统编程的概念
Linux 系统函数----与Linux操作系统内核 很近,它是Linux内核 提供给用户的 接口函数。
优点:种类多、功能强、效率高。常用的如 read write(IO系统函数)、fork(多进程系统函数)、pthread_create(多线程函数)、socket(网络通信函数)
缺点:是与特定的操作系统相对应的。在Linux下,我们一般称它为 系统函数;在windowds下,则一般称win32 API函数
C/C++标准库函数----调用 Linux系统函数 来实现的,因此它距离 Linux内核要远一些。
优点:因为已经标准化了,所以windows操作系统下,也可以直接调用,相当于跨平台的。
缺点:功能还不广泛,执行效率也低一些
其它函数库、自定义函数----都是直接或间接调用了 Linux系统函数、C标准函数库、C++标准函数(包括STL),因此,不属于Liunx系统函数
注意:如果调用了Linux系统函数,则这些函数就不能在windows下 直接调用了,即不能跨平台了。
二、Linux系统编程之 cocket网络编程
学习方法:
1、先要分析理解 现实当中,2个相距遥远的人,是如何通过通讯兵 来收发信息的。
2、根据,上述情况的分析,理解socket编程中的 3次握手、4次握手 的实际含义
3、利用电话总机、分机的概念,理解 套接字(电话插座)、绑定(电话插座和总机号、分机号绑定在一起)等socket函数
代码分析:
//服务器端代码
#include <QtCore/QCoreApplication>
#include "wrap.h"
#define MAXLINE 80
#define SERV_PORT 8000
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
struct sockaddr_in servaddr, cliaddr;
socklen_t cliaddr_len;
int listenfd, connfd;
char buf[MAXLINE];
char str[INET_ADDRSTRLEN];
int i, n;
listenfd = Socket(AF_INET, SOCK_STREAM, 0); //返回1个侦听套接字;错误时,会返回-1;AF_INET表示ipv4协议;SOCK_STREAM表示TCP;协议参数一般填0即可
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //因为pc机可以有多个IP地址,使用该宏,则均可以作为服务器ip地址
servaddr.sin_port = htons(SERV_PORT);
Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); //绑定成功 返回0;失败返回-1
Listen(listenfd, 20); //侦听成功返回0,否则返回-1. 20表示最多有20个客户端可以处于连接等待状态,其它的连接请求将被忽略
printf("Accepting connections ...\n");
cliaddr_len = sizeof(cliaddr);
connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len); //cliaddr是输出参数,将保存客户机的地址信息;cliaddr_len是输入输出参数,先是服务器段提供的长度,后根据客户端的情况被修改了这是为了防止缓冲区溢出。
while (1)
{
n = Read(connfd, buf, MAXLINE);
printf("received from %s at PORT %d\n", inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)), ntohs(cliaddr.sin_port));
for (i = 0; i < n; i++)
buf[i] = toupper(buf[i]);
Write(connfd, buf, n);
//Close(connfd);
}
return 0;
//return a.exec();
}
//客户机端代码
#include <QtCore/QCoreApplication>
#include "wrap.h"
#define MAXLINE 80
#define SERV_PORT 8000
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
struct sockaddr_in servaddr, cliaddr;
socklen_t cliaddr_len;
int listenfd, connfd;
char buf[MAXLINE];
char str[INET_ADDRSTRLEN];
int i, n;
listenfd = Socket(AF_INET, SOCK_STREAM, 0); //返回1个侦听套接字;错误时,会返回-1;AF_INET表示ipv4协议;SOCK_STREAM表示TCP;协议参数一般填0即可
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //因为pc机可以有多个IP地址,使用该宏,则均可以作为服务器ip地址
servaddr.sin_port = htons(SERV_PORT);
Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); //绑定成功 返回0;失败返回-1
Listen(listenfd, 20); //侦听成功返回0,否则返回-1. 20表示最多有20个客户端可以处于连接等待状态,其它的连接请求将被忽略
printf("Accepting connections ...\n");
cliaddr_len = sizeof(cliaddr);
connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len); //cliaddr是输出参数,将保存客户机的地址信息;cliaddr_len是输入输出参数,先是服务器段提供的长度,后根据客户端的情况被修改了这是为了防止缓冲区溢出。
while (1)
{
n = Read(connfd, buf, MAXLINE);
printf("received from %s at PORT %d\n", inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)), ntohs(cliaddr.sin_port));
for (i = 0; i < n; i++)
buf[i] = toupper(buf[i]);
Write(connfd, buf, n);
//Close(connfd);
}
return 0;
//return a.exec();
}
注意:
上述代码,实际上调用的是我们封装后的普通函数(第1个字母大写的函数)
封装文件为wrap.h 和wrap.cpp
封装代码、服务器端代码、客户端代码