客戶端
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <string.h> #include<arpa/inet.h> #include <error.h> #include <unistd.h> #include <arpa/inet.h> #include <netinet/in.h> #include <pthread.h> void* recvsocket(void* arg)//接受來着客戶端數據的線程 { int st = *(int*)arg; char s[1024]; while (1) { memset(s, 0, sizeof(s)); int rc = recv(st, s, sizeof(s), 0); if (rc <= 0)//代表socket被關閉(0)或者出錯(-1) { break; } printf("client receive:%s\n", s); } return NULL; } void* sendsocket(void* arg)//向服務端socket發送數據的線程 { int st = *(int*)arg; char s[1024]; while (1) { memset(s, 0, sizeof(s)); scanf("%s", s); int sc = send(st, s, strlen(s), 0); } } //執行 ./ClientLinux.out 127.0.0.1 8080 int main(int arg, char* args[]) { if (arg < 3) { printf("arg<3\n"); return - 1; } int port = atoi(args[2]); //第一步:初始化一個socket實例 int st = socket(AF_INET, SOCK_STREAM, 0); //第二步:定義一個IP地址結構並設置值 struct sockaddr_in addr; //內存初始化,將addr變量指向的內存簽n個字節用0進行初始化填充 memset(&addr, 0, sizeof(addr)); //設置采用的協議為TCP/IP協議 addr.sin_family = AF_INET; //設置端口號 addr.sin_port = htons(port); //設置IP地址 addr.sin_addr.s_addr = inet_addr(args[1]); //第三步:開始連接服務端 if (connect(st, (struct sockaddr*) & addr, sizeof(addr)) == -1) { printf("connect fail %s\n", strerror(errno)); return EXIT_FAILURE; } //第四步:初始化要發送的信息並且通過send函數發送數據 pthread_t thrd1, thrd2;//定義一個線程 pthread_create(&thrd1, NULL, recvsocket, &st); pthread_create(&thrd2, NULL, sendsocket, &st); pthread_join(thrd1,NULL); pthread_join(thrd2,NULL); close(st); getchar(); return EXIT_SUCCESS; }
服務端
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <string.h> #include<arpa/inet.h> #include <error.h> #include <unistd.h> #include <arpa/inet.h> #include <netinet/in.h> #include <pthread.h> void* recvsocket(void* arg)//接受來着客戶端數據的線程 { int st = *(int*)arg; char s[1024]; while (1) { memset(s, 0, sizeof(s)); int rc = recv(st, s, sizeof(s), 0); if (rc <= 0)//代表socket被關閉(0)或者出錯(-1) { printf("sercver recv fail:%d\n", rc); break; } printf("server receive:%s\n", s); } return NULL; } void* sendsocket(void* arg)//向客戶端socket發送數據的線程 { int st = *(int*)arg; char s[1024]; while (1) { memset(s, 0, sizeof(s)); scanf("%s", s); int sc = send(st, s, strlen(s), 0); } } //執行命令 ./ServerLinux.out 8080 int main(int arg, char* args[]) { if (arg < 2) { return -1; } int port = atoi(args[1]); int st = socket(AF_INET, SOCK_STREAM, 0); //setsockopt 設置socket的一個屬性,讓地址可以重用。 int on = 0; if (setsockopt(st, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { printf("setsockopt failed:%s\n", strerror(errno)); return EXIT_FAILURE; } struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(port); //INADDR_ANY表示這個服務器上的所有Ip地址。一台服務器可以有多個ip地址。將socket綁定到這個機器的所有ip地址上 addr.sin_addr.s_addr = htonl(INADDR_ANY); //將ip地址與server程序綁定 if (bind(st, (struct sockaddr*) & addr, sizeof(addr)) == -1) { printf("bind fail %s\n", strerror(errno)); return EXIT_FAILURE; } //server開始監聽。 20代表同時有多少個連接過來(20並發) if (listen(st, 20) == -1) { printf("listen fail %s\n", strerror(errno)); return EXIT_FAILURE; } //char s[1024]; int client_st = 0;//客戶端socket struct sockaddr_in client_addr;//客戶端IP pthread_t thrd1, thrd2;//定義一個線程 while (1) { memset(&client_addr, 0, sizeof(client_addr)); socklen_t len = sizeof(client_addr); //accept會阻塞,直到有客戶端連接過來。accept返回客戶端的描述符 client_st = accept(st, (struct sockaddr*) & client_addr, &len); if (client_st == -1) { printf("accept fail %s\n", strerror(errno)); return EXIT_FAILURE; } //打印客戶端的ip地址 printf("accept ip : %s\n", inet_ntoa(client_addr.sin_addr)); pthread_create(&thrd1, NULL, recvsocket, &client_st); pthread_create(&thrd2, NULL, sendsocket, &client_st); } close(st); getchar(); }