最近学习了网络编程,简单分享一下自己学习的内容
TCP协议简介
TCP向应用层提供了一个可靠的,有序的,面向连接的,基于字节流的全双工的通信协议。
它能提供高可靠性通信,即数据无误,数据无丢失,数据无失序,数据无重复。
三次握手协议
TCP是面向连接的。通过三次握手协议实现。
第一步:客户端向服务器端发送一个SYN=1,seq=x的TCP报文,并进入SYN_SEND状态,等待服务器确认。
第二步:服务器端收到客户端的报文后,返回一个SYN=1,ACK=1,seq=y,ack=x+1的报文,标识客户端的SYN被确认,此时服务器进入SYN_RECV状态。
第三步:客户端收到服务器的报文后,向服务器发送一个ACK=1,seq=x+1,ack=y+1的报文确认,客户端和服务器进入ESTAB_LISHED状态,完成TCP连接。
TCP CS搭建流程图
函数实现
客户端:实现了向服务器发送数据,创建了一个子线程来接受服务器转发的数据
1 #include <stdio.h>
2 #include <string.h>
3 #include <unistd.h>
4 #include <sys/types.h>
5 #include <sys/socket.h>
6 #include <arpa/inet.h>
7 #include <pthread.h>
8
9 int mysckfd;
10 void *recv_func(void *p)
11 {
12 char buf1[100];
13 while(1)
14 {
15 memset(buf1,0,sizeof(buf1));
16 int res = recv(mysckfd,buf1,sizeof(buf1),0);
17 if(res < 0)
18 {
19 puts("recv_func error");
20 break;
21 }
22 puts(buf1);
23 }
24 }
25 int main()
26 {
27 //socket 创建一个通信套接字
28 mysckfd = socket(AF_INET, SOCK_STREAM, 0);
29 if(mysckfd < 0)
30 {
31 puts("socket error.");
32 return -1;
33 }
34 puts("socket success.");
35 //connect 连接服务器端
36 int ret = -1;
37 struct sockaddr_in myser;
38 myser.sin_family = AF_INET;
39 myser.sin_port = htons(7777);
40 myser.sin_addr.s_addr = inet_addr("192.168.9.132");
41
42 ret = connect(mysckfd, (struct sockaddr *)&myser, sizeof(myser));
43 if(ret != 0)
44 {
45 puts("connect server error.");
46 close(mysckfd);
47 return -1;
48 }
49 puts("connect server success.");
50 //send发送函数
51 char buf[50];
52 pthread_t thread;
53 while(1)
54 {
55 memset(buf,0,sizeof(buf));
56 gets(buf);
57 send(mysckfd, buf, sizeof(buf), 0);
58 //创建一个线程进行接收
59 void *recv_func(void *);
60 pthread_create(&thread,NULL,recv_func,0);
61 }
62
63 //close
64 close(mysckfd);
65 return 0;
66 }
服务器端:使用多进程实现了服务器端同时处理多个客户端请求,并将收到的数据转发给源客户端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
//接受发送子函数
int recv_send_func(int connfd)
{
while(1)
{
char buf[100];
memset(buf, 0, sizeof(buf));
int ret = recv(connfd, buf, sizeof(buf), 0);
if(ret > 0)
{
puts(buf);
send(connfd,buf,sizeof(buf),0);
}
else if(ret == 0)
{
break;
}
}
}
//初始化子函数
int Init_func(unsigned short port)
{
//socket创建一个监听套接字
int myserfd = socket(AF_INET, SOCK_STREAM, 0);
if(myserfd < 0)
{
puts("socket error!");
return -1;
}
puts("socket success!");
//bind给服务器绑定端口号和IP,注意:端口号不能和已使用的端口号重复
int ret = -1;
struct sockaddr_in myser;
memset(&myser, 0, sizeof(myser));
myser.sin_family = AF_INET;
myser.sin_port = htons(port);
myser.sin_addr.s_addr = htonl(INADDR_ANY);
ret = bind(myserfd, (struct sockaddr *)&myser, sizeof(myser));
if(ret != 0)
{
puts("bind error!");
close(myserfd);
return -1;
}
puts("bind success!");
//listen监听客户端的连接请求
ret = listen(myserfd, 5);
if(ret != 0)
{
puts("listen error!");
close(myserfd);
return -1;
}
puts("listen success!");
return myserfd;
}
//主函数
int main()
{
int serfd = Init_func(7777);
int connfd = -1;
struct sockaddr_in mycli;
int len = sizeof(mycli);
while(1)
{
connfd = accept(serfd,(struct sockaddr *)&mycli,&len);
if(connfd > 0)
{
pid_t pid = fork();
if(pid == 0)
{
while(1)
{
recv_send_func(connfd);
}
close(connfd);
exit(0);
}
}
}
return 0;
}