最近学习网络连接的各种协议,决定先从TCP入手。
看了网上好多例子,然后自己动手用C做了一个TCP通信小工具。
本机是linux的,作为服务端;为了多学点东西,于是不辞辛苦装了台windows的虚拟机作为客户端;
简单总结了一下TCP的连接过程:
服务端:
初始化地址结构体
初始化套接字
绑定套接字和地址结构体
监听套接字
接受连接
开始自由通信
关闭套接字
客户端:
初始化服务器地址结构
初始化本机套接字
连接服务器
开始自由通信
关闭套接字
附上代码:
服务端(linux平台):
#include
#include
#include
#include
#include
#include
#include
//线程所需参数
typedef struct _Args
{
int socket_client;
}Args;
//接收信息的函数
void* GetMsg(void* arg);
int main(int argc,char *argv[])
{
//服务器地址结构体
struct sockaddr_in my_addr;
//初始化服务器地址
memset(&my_addr,0,sizeof(my_addr));
my_addr.sin_family=AF_INET;
my_addr.sin_addr.s_addr=INADDR_ANY;
my_addr.sin_port=htons(1188);
//套接字(个人理解:套接字就是协议的描述)
int socket_server;
//获得套接口描述符
socket_server=socket(PF_INET,SOCK_STREAM,0);
if(socket_server<=-1)
{
printf("socket error\n");
return 1;
}
//绑定套接字与地址
int result_bind = bind(socket_server,(struct sockaddr*)&my_addr,sizeof(struct sockaddr));
if(result_bind<=-1)
{
printf("bind error\n");
return 1;
}
//监听端口
listen(socket_server,2);
printf("waitind for connecting...\n");
//储存client地址
struct sockaddr_in client_addr;
//接受连接
int len_socket=sizeof(struct sockaddr);
int socket_client=accept(socket_server,(struct sockaddr*)&client_addr,&len_socket);
if(socket_client<=-1)
{
printf("accept error\n");
return 1;
}
//打印连接信息
printf("new client %s\n",inet_ntoa(client_addr.sin_addr) );
//欢迎信息
char* hello="hello friend!\n";
send(socket_client,hello,strlen(hello),0);
//线程接受信息所需参数
Args args;
args.socket_client=socket_client;
//启动线程
pthread_t thread;
pthread_create(&thread,NULL,&GetMsg,(void*)&args);
//发送信息
char msg[101];
memset(msg,'\0',101*sizeof(char));
while (strcmp(msg,"bye")!=0)
{
printf("send:\n\r");
memset(msg,'\0',100*sizeof(char));
scanf("%s",msg);
send(socket_client,msg,strlen(msg),0);
printf("\n");
}
pthread_join(thread,NULL);
close(socket_client);
close(socket_server);
return 0;
}
//接收信息
void* GetMsg(void* arg)
{
int client_addr=((Args*)arg)->socket_client;
char buffer[101];
memset(buffer,'\0',101*sizeof(char));
while(strcmp(buffer,"bye")!=0)
{
memset(buffer,'\0',100*sizeof(char));
recv(client_addr,buffer,100,0);
printf("\nrecv:\n%s\n\nsend:\n");
}
}
客户端(windows平台):
#include
#include
#include
#include
typedef struct _Arg
{
int socket_client;
}Arg;
void* GetMsg(void* args);
int main(int argc, char *argv[])
{
//初始化服务器地址
struct sockaddr_in server_addr; //服务器端网络地址结构体
memset(&server_addr,0,sizeof(struct sockaddr_in));
server_addr.sin_family=AF_INET; //设置为IP通信
server_addr.sin_addr.s_addr=inet_addr("192.168.1.105");//服务器IP地址
server_addr.sin_port=htons(1188); //服务器端口号
//初始化本机套接字
WORD versionRequired=MAKEWORD(2,2);
WSADATA wsaData;
if (0!=WSAStartup(versionRequired,&wsaData))//协议库的版本信息
{
printf("ERROR:客户端的嵌套字打开失败!\n");
return 1;//结束
}
SOCKET socket_client=socket(AF_INET,SOCK_STREAM,0);
//尝试连接
int result_connect=connect(socket_client,(struct sockaddr*)&server_addr,sizeof(struct sockaddr));
if(result_connect<=-1)
{
printf("connect error\n");
return 1;
}
//启动线程
Arg arg;
arg.socket_client=socket_client;
pthread_t thread;
pthread_create(&thread,NULL,GetMsg,(void*)&arg);
//发送
char msg[101];
memset(msg,'\0',101*sizeof(char));
while(strcmp(msg,"bye")!=0)
{
printf("send:\n");
memset(msg,'\0',100*sizeof(char));
scanf("%s",msg);
send(socket_client,msg,strlen(msg),0);
printf("\n");
}
pthread_join(thread,NULL);
closesocket(socket_client);
WSACleanup();
return 0;
}
void* GetMsg(void* args)
{
int socket_client=((Arg*)args)->socket_client;
char buffer[101];
memset(buffer,'\0',101*sizeof(char));
while(strcmp(buffer,"bye")!=0)
{
memset(buffer,'\0',100*sizeof(char));
recv(socket_client,buffer,100,0);
printf("\nrecv:\n%s\n\nsend:\n",buffer);
}
}
这只是一个简单的、不完整的、有BUG的小程序,还有很多没有做到位的地方,望高手指点