最近学习网络连接的各种协议,决定先从TCP入手。
看了网上好多例子,然后自己动手用C做了一个TCP通信小工具。
本机是linux的,作为服务端;为了多学点东西,于是不辞辛苦装了台windows的虚拟机作为客户端;
简单总结了一下TCP的连接过程:
服务端:
- 初始化地址结构体
- 初始化套接字
- 绑定套接字和地址结构体
- 监听套接字
- 接受连接
- 开始自由通信
- 关闭套接字
客户端:
- 初始化服务器地址结构
- 初始化本机套接字
- 连接服务器
- 开始自由通信
- 关闭套接字
附上代码:
服务端(linux平台):
#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <string.h> #include <pthread.h> //线程所需参数 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 <stdio.h> #include <winsock2.h> #include <string.h> #include <pthread.h> 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的小程序,还有很多没有做到位的地方,望高手指点
时间: 2024-10-18 03:57:15