网络编程概念
网络编程包括地址和数据
地址:IP地址、端口号 数据:协议(格式)
1.协议TCP/UDP对比:
*
TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前,不需要建立连接。
*
TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错、不丢失、不充分且按序到达;UDP尽最大努力交付,即不保证可靠交付
*
TCP面向字节流,实际上是TCP把数据看成一串无结构的字节流;UDP是面向报文的。UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)。
*
每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信。
*
TCP首部开销20字节;UDP的首部开销小,只有8个字节。
*
TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道。
2.端口号作用
*
一台拥有IP地址的主机可以提供许多服务,比如web服务,FTP服务、SMTP服务等。 这些服务完全可以通过1个IP地址来实现。那么主机是怎么样区分不同的网络服务呢? 显然不能只靠IP地址,因为IP地址与网络服务的关系是一对多的关系。实际上是通过“IP地址+端口号”来区分不同的服务的。端口提供了一种访问通道,服务器一般都是通过知名端口号来识别。例如,对于每个TCP/IP实现来说,FTP服务器的TCP端口号都是21,每个Telnet服务器的TCP端口号都是23,每个TFTP(简单文件传送协议)服务器的UDP端口号都是69。
3.字节序
*
字节序是指多字节数据在计算机内存中存储或者网络传输时各字节的存储顺序。 分为小端字节序(Little endian) 和 大端字节序(Big endian) //网络字节序 = 大端字节序
小端字节序:将低序字节存储在起始地址。
大端字节序:将高序字节存储在起始地址。
网络编程过程
①int socket(int domain, int type, int protocol); //连接协议 创建套接字
②int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen); //IP号端口号与相应描述字赋值函数
③listen()函数 //监听设置函数
④accept()函数//连接客户端,返回新的套接字
⑤数据收发 //read 、 write 等等
客户端代码:
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
//#include <linux/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
char buf1[128]= {0};
char buf[1024] = {0};
int sockfd;
// 1.socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in ct_connect;
ct_connect.sin_family = AF_INET;
ct_connect.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1], &ct_connect.sin_addr);
int n_connect;
n_connect = connect(sockfd, (struct sockaddr *)&ct_connect,
sizeof(struct sockaddr_in));
if (n_connect == 0) {
printf("connect success!\n");
}
int n_fork = fork();
if(n_fork == 0){
while(1){
printf("请输入消息:\n");
scanf("%s", buf);
write(sockfd, buf, 128);
memset(buf,0,sizeof(buf));
if ((write(sockfd, buf, 128)) == -1) {
perror("write");
exit(-1);
}
}
}
while(1){
read(sockfd,buf1,128);
printf("读取内容:%s\n",buf1);
memset(buf1,0,sizeof(buf1));
}
return 0;
}
服务端代码:
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
//#include <linux/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char **argv) {
int sockfd;
// 1.socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
// 2.bind
struct sockaddr_in skaddr;
struct sockaddr_in ac_addr;
memset(&skaddr, 0, sizeof(struct sockaddr_in));
memset(&ac_addr, 0, sizeof(struct sockaddr_in));
skaddr.sin_family = AF_INET;
skaddr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1], &skaddr.sin_addr);
int n_bind;
n_bind =
bind(sockfd, (struct sockaddr *)&skaddr, sizeof(struct sockaddr_in));
if (n_bind == -1) {
perror("bind");
exit(-1);
}
// 3.listen
int n_listen;
n_listen = listen(sockfd, 10);
printf("n_listen=%d\n", n_listen);
// 4.accept
int c_fd;
int len = sizeof(struct sockaddr_in);
char buf[128] = {0};
char buf1[128] = {0};
int n_read;
c_fd = accept(sockfd, (struct sockaddr *)&ac_addr, &len);
printf("connect success:%s\n", inet_ntoa(ac_addr.sin_addr));
int n_fork = fork();
if (n_fork == 0) {
while (1) {
memset(buf, 0, sizeof(buf));
n_read = read(c_fd, buf, 128);
printf("获取内容:%s\n", buf);
}
}
while (1) {
gets(buf1);
write(c_fd, buf1, 128);
memset(buf1, 0, sizeof(buf1));
}
return 0;
}