系统编程进程通信方式: 管道/信号/消息队列/共享内存 -> 特点: 只能在同一台主机内部通信。
网络编程进程通信方式: 套接字 -> 特点: 可以实现同一个局域网中不同主机之间通信。
TCP协议 -> Tranmission Control Protocol 传输控制协议 -> 面向有连接套接字编程。(打电话)
UDP协议 -> User Data Protocol 用户数据包协议 -> 面向无连接套接字编程。(寄信)
socket在英文被翻译为套接字,排插,插座。(因为插座种类有很多种,就好像很多种协议)
socket还是一种特殊的文件描述符。(因为socket套接字文件描述符不能通过open函数得到)
socket还是一个创建套接字的函数。
正常来讲,文件描述符是通过open()得到的。
例子: int fd = open("1.txt"); -> fd就是代表"1.txt"的文件描述符。
套接字的文件描述符怎么来的?
例子: int sockfd = socket(TCP协议); -> sockfd就是TCP协议的套接字
例子: "192.168.90.2"
在一个局域网中,每一台主机都会有一个IP地址,这个IP地址就是这台主机唯一的标识符。
每一个IP地址都是32位。
在一个局域网中,两个主机之间需要通信,除了IP地址要在同一个局域网中之外,还需要两者使用同一个端口号。
系统已经占用的端口号: 0~1023 (用户不能使用)
用户有效的端口号: 1024~65535 (用户可以使用)
端口号是16位。
例子: 主机A --> 主机B
IP地址必须在同一个网段 192.168.90.2 192.168.90.19
端口号必须一致 50001 50001
gec@ubuntu:~$ ifconfig
lo Link encap:Local Loopback -> 当前只有lo回环IP,没有以太网卡,需要主动激活网卡。
inet addr:127.0.0.1 Mask:255.0.0.0
gec@ubuntu:~$ sudo ifconfig eth0 up
gec@ubuntu:~$ ifconfig
eth0 Link encap:Ethernet HWaddr 00:0c:29:5d:9c:76
inet6 addr: fe80::20c:29ff:fe5d:9c76/64 Scope:Link -> 已经激活以太网卡,但是还没设置IP地址。
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
gec@ubuntu:~$ sudo vi /etc/network/interfaces
auto lo
iface lo inet loopback
audo eth0 -> 修改: auto eth0
iface eth0 inet static
address 192.168.0.245 -> 修改:address 192.168.90.xx
gateway 192.168.0.1 -> 修改:gateway 192.168.90.1
netmask 255.255.255.0
保存退出!
gec@ubuntu:~$ sudo /etc/init.d/networking restart
* Running /etc/init.d/networking restart is deprecated because it may not enable again some interfaces
* Reconfiguring network interfaces... [OK]
gec@ubuntu:~$ ifconfig
eth0 Link encap:Ethernet HWaddr 00:0c:29:5d:9c:76
inet addr:192.168.90.4 Bcast:192.168.90.255 Mask:255.255.255.0
练习1: 设置IP地址
练习2: windows/ubuntu/ARM互相ping通。
int sockfd;
sockfd = socket(AF_INET,SOCK_STREAM,0);
printf("sockfd = %d\n",sockfd); //3
/* Address to accept any incoming messages. */
#define INADDR_ANY ((unsigned long int) 0x00000000) -> 自动获取主机的IP地址。
struct sockaddr_in srvaddr;
socklen_t len = sizeof(srvaddr);
bzero(&srvaddr,len);
srvaddr.sin_family = AF_INET; //协议
srvaddr.sin_port = htons(atoi(argv[1])); //端口号
srvaddr.sin_addr.s_addr = htonl(INADDR_ANY); //服务器的IP
bind(sockfd,(struct sockaddr *)&srvaddr,len);
listen(sockfd,5);
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
char *inet_ntoa(struct in_addr in);
struct sockaddr_in cliaddr;
int connfd;
connfd = accept(sockfd,(struct sockaddr *)&cliaddr,&len); //阻塞!
if(connfd > 0)
{
printf("new connection:%s\n",(char *)inet_ntoa(cliaddr.sin_addr));
}
char buf[50];
while(1)
{
bzero(buf,sizeof(buf));
recv(connfd,buf,sizeof(buf),0);
printf("from Jack:%s",buf);
if(strncmp(buf,"quit",4) == 0)
{
break;
}
}
close(connfd);
close(sockfd);
int sockfd;
sockfd = socket(AF_INET,SOCK_STREAM,0);
printf("sockfd = %d\n",sockfd); //3
struct sockaddr_in srvaddr;
socklen_t len = sizeof(srvaddr);
bzero(&srvaddr,len);
srvaddr.sin_family = AF_INET;//协议
srvaddr.sin_port = htons(atoi(argv[2]));
inet_pton(AF_INET,argv[1],&srvaddr.sin_addr);
int ret = connect(sockfd,(struct sockaddr *)&srvaddr,len);
if(ret == -1)
printf("connnect error!\n");
char buf[50];
while(1)
{
bzero(buf,sizeof(buf));
fgets(buf,sizeof(buf),stdin);
send(sockfd,buf,strlen(buf),0);
if(strncmp(buf,"quit",4) == 0)
{
break;
}
}
close(sockfd);
练习1:自己跟自己通信。
练习2:自己跟同桌通信。
练习3:尝试写一个回射服务器。
char buf[50];
while(1)
{
bzero(buf,sizeof(buf));
recv(connfd,buf,sizeof(buf),0); -> 客户端发送什么数据过来
send(connfd,buf,strlen(buf),0); -> 就回发什么数据给客户端
if(strncmp(buf,"quit",4) == 0)
{
break;
}
}
练习4:实现客户端与服务器之间进行收和发!
原文:https://www.cnblogs.com/zjlbk/p/11365855.html