一.网络编程概述
网络中进程间的通信首先需要识别进程所在主机在网络中的唯一标识即网络层的IP地址主机上的进程可以通过传输层的协议与端口号识别。
与单机的进程间通信的区别: 进程间通信包括管道、消息队列、共享内存、信号以及信号量。特点都是依赖于linux内核。所以缺点就是无法进行多机通信。 网络编程注意点: (1)地址:ip地址和端口号 ;(2)协议(http/tcp/udp…);
1.socket网络编程(套接字): Socket是应用层与TCP/IP协议族通信的中间软件抽象层是一种编程接口。Socket屏蔽了不同网络协议的差异支持面向连接(Transmission Control Protocol - TCPIP)和无连接(User Datagram Protocol-UDP 和 Inter-Network Packet Exchange-IPX)的传输协议。
1.TCP与UDP对比
- 1).TCP面向连接(如打电话要先拨号建立连接);
UDP是无连接的,即发送数据之前不需要建立连接。 - 2).TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;
UDP尽最大努力交付,即不保证可靠交付。 - 3).TCP面向字节流,实际上TCP把数据看成一连串无结构的字节流;
UDP是面向报文的,UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)。 - 4).每一条TCP连接只能是点到点的;
UDP支持一对一,一对多,多对一,多对多的交互通信。 - 5).TCP首部开销20字节;
UDP首部开销小,只有8个字节。 - 6).TCP的逻辑通信信道是全双工的可靠信道;
UDP则是不可靠信道。
2.端口号作用
一台拥有ip地址的主机可以提供许多服务,比如web服务、FTP服务、SMTP服务等;这些服务完全可以通过一个ip地址来实现。 那么主机是怎么区分不同的网络服务呢? 显然不能只靠ip地址,因为ip地址和网络服务的关系是一对多。 实际上通过“IP地址+端口号”来区分不同的服务。 端口提供一种访问通道,服务器一般都是通过知名端口号来识别的。例如:对于每个TCP/IP实现来说,FTP的TCP端口号都是21,每个Telnet服务器的TCP端口号都是23,每个TPTP(简单文件传送协议)服务器的UDP端口号都是69.
二.字节序
1.概述
字节序是指多字节数据在计算机内存中存储或者网络传输时各字节的存储顺序。
2.常见字节序
(1)Little endian 小端字节序 将低序字节存储在起始地址。(x86系列CPU都是little-endian的字节序) (2)Big endian 大端字节序 将高序字节存储在起始地址 网络字节序 = 大端字节序
三.Socket 编程逻辑
Socket编程的一般流程如下:
四.socket常用api
1、socket int socket(int domain, int type, int protocol); 创建一个Socket
2、bind int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 把一个地址族中的特定地址赋给socket.
3、listen int listen(int sockfd, int backlog); 设置sockfd套接字为监听套接字. 4、accept int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); 接收客户端的请求建立连接套接字.
5、connect int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
6、数据传输操作 ssize_t read(int fd, void *buf, size_t count); read函数是负责从连接套接字fd中读取内容。 还有wirte函数与文件操作一样。也可以用send和recv函数实现数据收发。
7、close int close(int fd); 关闭断开连接套接字
fd参数表示要断开的连接套接字
8.地址转换API int inet_aton(const char *cp, struct in_addr *inp); 把字符串形式的“192.168.1.123”转为网络能识别的形式。 char *inet_ntoa(stuct in_addr in); 把网络格式的ip地址转为字符串形式。 9.字节序转API
五.代码示例
实现服务端与客户端通信 服务端代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
void listen_con(int c_fd, int id)
{
int n_read;
char readbuf[128] = {0};
char msg[128] = {0};
if(fork() == 0)
{
while(1)
{
memset(msg,0,sizeof(msg));
scanf("%s",msg);
write(c_fd,msg,strlen(msg));
}
}
while(1)
{
memset(readbuf,0,sizeof(readbuf));
n_read = read(c_fd,readbuf,128);
if(n_read == -1)
{
printf("client %d close!\n",id);
}
else
{
if(strcmp(readbuf,"exit\n") == 0)
{
printf("id %d exited.\n",id);
break;
}
printf("ID_%d:%s\n",id,readbuf);
}
}
close(c_fd);
}
int main(int argc,char **argv)
{
int s_fd,c_fd;
int c_size,mark=0;
struct sockaddr_in my_addr;
struct sockaddr_in c_addr;
s_fd = socket(AF_INET,SOCK_STREAM,0);
if(s_fd == -1)
{
perror("socket");
exit(-1);
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1],&my_addr.sin_addr);
if(bind(s_fd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr)) == -1)
{
perror("bind");
exit(-1);
}
listen(s_fd,10);
while(1)
{
c_size = sizeof(struct sockaddr_in);
c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&c_size);
if(c_fd == -1)
{
perror("accept");
exit(-1);
}
printf("get connect:%d\n",++mark);
if(fork() == 0)
{
close(s_fd);
listen_con(c_fd,mark);
exit(0);
}
}
close(s_fd);
printf("server-------closed.\n");
return 0;
}
客户端代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc,char **argv)
{
int s_fd;
int n_read;
char msg[128] = {0};
char readbuf[128] = {0};
struct sockaddr_in c_addr;
s_fd = socket(AF_INET,SOCK_STREAM,0);
if(s_fd == -1)
{
perror("socket");
exit(-1);
}
c_addr.sin_family = AF_INET;
c_addr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1],&c_addr.sin_addr);
if(connect(s_fd,(struct sockaddr*)&c_addr,sizeof(struct sockaddr)) == -1)
{
perror("connect error!\n");
exit(1);
}
while(1)
{
if(fork() == 0)
{
while(1)
{
memset(msg,0,sizeof(msg));
printf("client-----:");
scanf("%s",msg);
write(s_fd,msg,strlen(msg));
}
}
while(1)
{
memset(readbuf,0,sizeof(readbuf));
n_read = read(s_fd,readbuf,128);
if(n_read == -1)
{
printf("client close\n");
}
else
{
printf("s: %s\n",readbuf);
}
}
}
close(s_fd);
return 0;
运行结果:
|