Linux _TCP 浅解
网络套接字通信(基于TCP)
- 相关头文件
#include <netinet/in.h>
#include <arpa/inet.h>
qianjie
开发步骤
开发步骤与文件系统套接字相似,区别仅在于:
1)创建套接字时使用的参数不同
文件系统套接字,使用的域参数为 AF_UNIX
网络套接字,使用的域参数为 AF_INET2) 套接字所使用的地址类型不同
文件系统套接字使用的地址类型:struct sockaddr_un
文件系统套接字使用的地址类型:struct sockaddr_in
注意:server_addr.sin_addr.s_addr表示IP地址,
是一个4字节数,而不是字符串,可使用inet_addr函数进行转换
例:server_addr.sin_addr.s_addr = inet_addr(“127.0.0.1”)补充:回环地址(“127.0.0.1”, 即相当于本地的IP地址) UNIX和Linux都配置了一个回路网络,在该网络中,只有一个IP地址,即127.0.0.1 INADDR_ANY, 表示该服务器可接受任意IP地址的客户端
3)套接字所使用的地址的设置方式不同
网络套接字所使用的地址,需要设置端口号和IP地址。
(1)端口号的设置
端口号是一个无符号16数
例: server_addr.sin_port = 9000;端口号的选择: 选择1024以上的任意一个未使用的端口好即可。(1024以内的端口号为系统内部使用) 查看已使用的端口号: cat /etc/services 客户端程序中指定的端口号要与服务器套接字使用的端口号一致 (2) 主机字节序与网络字节序 不同主机的字节序(大小端格式)可能不同。 而在网络上传输时,使用统一的网络字节序(大端格式)。 所以,在设置端口号时,需要进行字节序转换,否则将导致错误。 (因为,当通过TCP/IP协议传输时,端口号本身也包含在被传输数据中。) 使用inet_addr转换IP地址时,同时自动转换为网络字节序。 主机字节序和网络字节序的转换: htonl 把主机的无符号长整形转换为标准的网络字节序 htons 把足迹的无符号短整形转换为标准的网络字节序 例:server_addr.sin_port = htons(9000);
4)步骤总结:
基于TCP的网络套接字通信
服务器端
(1) 创建一个网络套接字
(2) 设置服务器地址
(3) 绑定该套接字,使得该套接字和对应的端口关联起来。
(4) 创建套接字队列, 保存进入该服务器的客户端请求
(5) 循环处理客户端请求
使用accept等待并接收客户端请求
收到客户端请求后,accept返回一个新的socket(表示该客户端连接)
使用这个新的socket,对客户端进行“读写“
处理完毕后,关闭这个新的socket客户端
(1) 创建一个套接字
(2) 设置服务器地址
(3) 使用该socket和服务器地址连接服务器(connect)
(4) 使用该socket发送和接受数据。
(5) 关闭该socket5) 注意
注意服务器端read的返回值:
当客户端还没有connect进入时,服务器端的read将被一直阻塞
当客户端已经connect进入时,
如果客户端还没有write,服务器端的read也将一直被阻塞
客户端write成功后,服务器端的read不再阻塞,返回实际读取的字节数。
当客户端关闭对应套接字时,服务器端的read不再阻塞, 返回0实例:server2.c
client2.c
实例
编写一个实时文字聊天程序。
用网络套接字实现。
客户端和服务器端进行“聊天”
直到客户端或者服务器端输入exit,就结束聊天(即服务器和客户端都退出)
提示:服务器端和客户端,分别使用两个进程或者两个线程,
用来分别处理发送数据和接受数据。
server3.c
client3.c
demo
client2.c
#include <sys/un.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
//#define SERVER_SOCKET_FILE "/tmp/server_socket"
int main(void)
{
int sockfd;
struct sockaddr_in server_addr;
int ret;
int c;
// ¥¥Ω®“ª∏ˆÃ◊Ω”◊÷
sockfd = socket(AF_INET, SOCK_STREAM, 0);
// …Ë÷√∑˛ŒÒ∆˜µÿ÷∑
server_addr.sin_family = AF_INET;
//strcpy(server_addr.sun_path, SERVER_SOCKET_FILE);
server_addr.sin_addr.s_addr = inet_addr("10.10.0.9"); //"127.0.0.1
server_addr.sin_port = htons(9000);
// ¡¨Ω”∑˛ŒÒ∆˜
ret = connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
if (ret == -1) {
perror("connet failed!\n");
exit(1);
}
// œÚ∑˛ŒÒ∆˜∑¢ÀÕ ˝æ›
c = 'm';
write(sockfd, &c, 1);
// ¥”∑˛ŒÒ∆˜∂¡»° ˝æ›
read(sockfd, &c, 1);
printf("get data: %c\n"````````````
c);
close(sockfd);
return 0;
}
server2.c
#include <sys/un.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
//#define SERVER_SOCKET_FILE "/tmp/server_socket"
int main(void)
{
int server_sockfd;
int client_sockfd;
char ch;
//”√”⁄UNIXœµÕ≥ƒ⁄≤øÕ®–≈µƒµÿ÷∑£¨ struct sockaddr_un
//struct sockaddr_un server_addr;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int client_addr_len;
/* …æ≥˝“‘«∞µƒŒƒº˛œµÕ≥Ã◊Ω”◊÷À˘∂‘”¶µƒŒƒº˛ */
//unlink(SERVER_SOCKET_FILE);
// ¥¥Ω®“ª∏ˆŒƒº˛œµÕ≥Ã◊Ω”◊÷(”√”⁄±æª˙ƒ⁄µƒÕ®–≈)
//server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
// …Ë÷√∑˛ŒÒ∆˜µÿ÷∑
server_addr.sin_family = AF_INET; //µÿ÷∑µƒ”Ú£¨œ‡µ±”⁄µÿ÷∑µƒ¿‡–Õ, AF_UNIX±Ì æµÿ÷∑Œª”⁄UNIXœµÕ≥ƒ⁄≤ø
server_addr.sin_addr.s_addr = INADDR_ANY;
//strcpy(server_addr.sun_path, SERVER_SOCKET_FILE);
server_addr.sin_port = htons(9000);
// ∞Û∂®∏√Ã◊Ω”◊÷£¨ πµ√∏√Ã◊Ω”◊÷∫Õ∂‘”¶µƒœµÕ≥Ã◊Ω”◊÷Œƒº˛πÿ¡™∆¿¥°£
bind(server_sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
// ¥¥Ω®Ã◊Ω”◊÷∂”¡–£¨ ±£¥ÊΩ¯»Î∏√∑˛ŒÒ∆˜µƒøÕªß∂À«Î«Û°£
listen(server_sockfd, 5);
// —≠ª∑¥¶¿ÌøÕªß∂À«Î«Û
while (1) {
printf("server waiting\n");
// µ»¥˝≤¢Ω” ’øÕªß∂À«Î«Û
client_addr_len = sizeof(client_addr);
//client_sockfd = accept(server_sockfd, (struct sockaddr*)&client_addr, &client_addr_len);
client_sockfd = accept(server_sockfd, 0, 0);
// ∂¡»°øÕªß∂À«Î«Û
read(client_sockfd, &ch, 1);
//¥¶¿ÌøÕªß∂À ˝æ›
ch++;
// œÚøÕªß∂À∑¢ÀÕΩ·π˚ ˝æ›
write(client_sockfd, &ch, 1);
// πÿ±’øÕªß∂ÀÃ◊Ω”◊÷
close(client_sockfd);
}
return 0;
}
client3.c
#include <sys/un.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#define BUFF_SIZE 1024
int main(void)
{
int sockfd;
struct sockaddr_in server_addr;
int ret;
int c;
int pd;
char buff[BUFF_SIZE];
// ¥¥Ω®“ª∏ˆÃ◊Ω”◊÷
sockfd = socket(AF_INET, SOCK_STREAM, 0);
// …Ë÷√∑˛ŒÒ∆˜µÿ÷∑
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr("10.0.0.4");
//server_addr.sin_port = 9734;
server_addr.sin_port = htons(9000);
// ¡¨Ω”∑˛ŒÒ∆˜
ret = connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
if (ret == -1) {
perror("connet failed!\n");
exit(1);
}
pd = fork();
if (pd == -1) {
perror("create process failed!\n");
exit(1);
} else if (pd == 0) {
// ◊”Ω¯≥Ã∑¢ÀÕ ˝æ›
while (1) {
bzero(buff, sizeof(buff));
fgets(buff, sizeof(buff), stdin);
if (strncmp(buff, "exit", 4) == 0) {
printf("client input exit!\n");
break;
}
write(sockfd, buff, strlen(buff)-1);
}
} else {
while (1) {
bzero(buff, sizeof(buff));
ret = read(sockfd, buff, sizeof(buff));
if (ret == 0) {
printf("The other side had closed!\n");
break;
}
printf("%s\n", buff);
}
}
close(sockfd);
if (pd == 0) {
kill(getppid(), SIGKILL);
} else {
kill(pd, SIGKILL);
}
return 0;
}
server3.c
#include <sys/un.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#define BUFF_SIZE 1024
int main(void)
{
int server_sockfd;
int client_sockfd;
char ch;
int pd;
int ret;
char buff[BUFF_SIZE];
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int client_addr_len;
server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
// …Ë÷√∑˛ŒÒ∆˜µÿ÷∑
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY; //inet_addr("10.10.0.9");
//server_addr.sin_port = 9734;
server_addr.sin_port = htons(9000);
// ∞Û∂®∏√Ã◊Ω”◊÷£¨ πµ√∏√Ã◊Ω”◊÷∫Õ∂‘”¶µƒœµÕ≥Ã◊Ω”◊÷Œƒº˛πÿ¡™∆¿¥°£
bind(server_sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
// ¥¥Ω®Ã◊Ω”◊÷∂”¡–£¨ ±£¥ÊΩ¯»Î∏√∑˛ŒÒ∆˜µƒøÕªß∂À«Î«Û°£
listen(server_sockfd, 5);
printf("server waiting\n");
// µ»¥˝≤¢Ω” ’øÕªß∂À«Î«Û
client_addr_len = sizeof(client_addr);
//client_sockfd = accept(server_sockfd, (struct sockaddr*)&client_addr, &client_addr_len);
client_sockfd = accept(server_sockfd, 0, 0);
pd = fork();
if (pd == -1) {
perror("create process failed!\n");
exit(1);
} else if (pd == 0) {
while(1) {
bzero(buff, sizeof(buff));
fgets(buff, sizeof(buff), stdin);
if (strncmp(buff, "exit", 4) == 0) {
break;
}
// ◊”Ω¯≥Ã÷–£¨∑¢ÀÕ ˝æ›
ret = write(client_sockfd, buff, strlen(buff) -1);
}
} else {
while(1) {
// ∏∏Ω¯≥Ã÷–£¨Ω” ’ ˝æ›
bzero(buff, sizeof(buff));
ret = read(client_sockfd, buff, sizeof(buff));
if (ret == 0) {
printf("The other side had closed!\n");
break;
}
printf("%s\n", buff);
}
}
close(client_sockfd);
close(server_sockfd);
if (pd == 0) {
kill(getppid(), SIGKILL);
} else {
kill(pd, SIGKILL);
}
return 0;
}