Socket(套接字)
一、什么是Socket?
在TCP/IP协议中,“IP地址+TCP/UDP端口号”可以唯一标识网络中的一个进程。IP地址+TCP/UDP端口号就是Socket。
在TCP协议中,建立连接的两个进程各自有一个socket来标识。这样,这两个进程组成了一个socket pair就唯一标识一个连接。网络连接是一对一的。
二、网络数据流的大小端
网络数据流有大小端之分,发送主机通常将发送缓冲区中方的数据按内存地址从低到高的顺序发出,接收主机把从网络上接收到的字节依次保存在接收缓冲区,也是按内存地址从高到低的顺序保存。因此,网络数据流规定,先发出的数据是低地址,后发出的数据是高地址。
TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节。
三、需用函数
为使网络程序具有可移植性,使同样的c代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换
socket地址的数据类型及相关函数
struct sockaddr
16位地址类型+14字节地址数据
struct sockaddr_in
16位地址类型(AF_INET)+16位端口号+32位IP地址+8字节填充
struct sockaddr_un
16位地址类型(AF_UNIX)+108字节路径名
bind函数
accept函数
connect函数
字符串转in_addr的函数和in_addr转字符串的函数
代码实现
server.c
/*************************************************************************
> File Name: server.c
> Author: ZX
> Mail: 18829897183@163.com
> Created Time: Tue 07 Mar 2017 10:46:18 PM PST
************************************************************************/
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<stdlib.h>
int startup(int _port, char* _ip)
{
//creat socket
int sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock < 0)
{
perror("socket");
exit(1);
}
struct sockaddr_in local;
local.sin_family = AF_INET;
local.sin_port = htons(_port);
local.sin_addr.s_addr = inet_addr(_ip);
//bind socket
if( bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0 )
{
perror("bind");
exit(2);
}
//listen socket
if( listen(sock, 5) < 0 )
{
perror("listen");
exit(3);
}
return sock;
}
int main(int argc, char* argv[])
{
if(argc != 3)
{
printf("Usage: %s [local_ip] [local_port]\n",argv[0]);
return 1;
}
int listen_sock = startup(atoi(argv[2]), argv[1]);
struct sockaddr_in remote;
socklen_t len = sizeof(remote);
while(1)
{
int sock = accept(listen_sock, (struct sockaddr*)&remote, &len);
if( sock < 0)
{
perror("accept");
continue;
}
printf("get a client, ip: %s port; %d\n",inet_ntoa(remote.sin_addr),ntohs(remote.sin_port));
char buf[1024];
while(1)
{
ssize_t s = read(sock, buf, sizeof(buf)-1);
if(s > 0)
{
buf[s] = 0;
printf("client# %s\n",buf);
}
else
{
printf("client is quit!\n");
break;
}
}
close(sock);
}
// printf("I am server!\n");
return 0;
}
client.c
/*************************************************************************
> File Name: client.c
> Author: ZX
> Mail: 18829897183@163.com
> Created Time: Tue 07 Mar 2017 10:46:28 PM PST
************************************************************************/
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<stdlib.h>
static void usage(char* porc)
{
printf("Usage: %s [ip] [port]\n",porc);
}
int main(int argc, char* argv[])
{
if(argc != 3)
{
usage(argv[0]);
return 1;
}
int sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock < 0)
{
perror("sock");
return 2;
}
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(argv[1]);
server.sin_port = htons(atoi(argv[2]));
socklen_t len = sizeof(server);
if(connect(sock, (struct sockaddr*)&server, len) < 0)
{
perror("connect");
return 3;
}
char buf[1024];
while(1)
{
printf("%s\n",buf);
fflush(stdout);
ssize_t s = read(0, buf, sizeof(buf)-1);
buf[s] = 0;
write(sock, buf, sizeof(buf)-1);
}
close(sock);
return 0;
}
Makefile
.PHONY:all
all:server client
client:client.c
gcc -o $@ $^
server:server.c
gcc -o $@ $^
.PHONY:clean
clean:
rm -f server client
编译环境:CenOs 6.5
语言:C语言
转载请注明原文地址: https://ju.6miu.com/read-23707.html