在TCP/IP协议中,“IP地址+TCP或UDP端口号”唯一标识网络通讯中的一个进程,“IP地址+端口号”就称为socket。
下图展示了TCP的通信过程
在Linux系统下,使用TCP协议进行socket通信。
- 服务器端:
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <ctype.h>
#define SERV_PORT 7777
int main(void)
{
int sfd, cfd;
int i, len;
struct sockaddr_in serv_addr, client_addr;
char buf[4096], client_ip[128];
socklen_t addr_len;
//AF_INET:ipv4 SOCK_STREAM:流协议 0:默认协议(tcp,udp)
sfd = socket(AF_INET, SOCK_STREAM, 0);
//绑定前先构造出服务器地址
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
//网络字节序
serv_addr.sin_port = htons(SERV_PORT);
//INADDR_ANY主机所有ip
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(sfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
//服务器能接收并发链接的能力
listen(sfd, 128);
printf("wait for connect ...\n");
addr_len = sizeof(client_addr);
//阻塞,等待客户端链接,成功则返回新的文件描述符,用于和客户端通信
cfd = accept(sfd, (struct sockaddr *)&client_addr, &addr_len);
printf("client IP:%s\t%d\n",
inet_ntop(AF_INET, &client_addr.sin_addr.s_addr, client_ip, sizeof(client_ip)),
ntohs(client_addr.sin_port));
while (1) {
//阻塞接收客户端数据
len = read(cfd, buf, sizeof(buf));
write(STDOUT_FILENO, buf, len);
//处理业务
for (i = 0; i < len; i++)
buf[i] = toupper(buf[i]);
//返回给客户端结果
write(cfd, buf, len);
}
close(cfd);
close(sfd);
return 0;
}
- 客户端:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#define SERV_PORT 7777
int main(int argc, char *argv[])
{
int sfd, len;
struct sockaddr_in serv_addr;
char buf[4096];
if (argc < 2) {
printf("./client serv_ip\n");
return 1;
}
sfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERV_PORT);
inet_pton(AF_INET, argv[1], &serv_addr.sin_addr.s_addr); //192.168.1.111 将字符串,转为网络字节序
//htonl(INADDR_ANY); 本地的字节序,转为网络的字节序(server)
connect(sfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
while (fgets(buf, sizeof(buf), stdin)) { //将键盘上输入的字符存入buf中
write(sfd, buf, strlen(buf)); //将buf中的数据写到服务器那
len = read(sfd, buf, sizeof(buf)); //读取服务器发来的数据,并存入buf中
write(STDOUT_FILENO, buf, len); //将buf中的数据写到屏幕上
}
return 0;
}
运行示例: